# SvgThemed

A React SVG wrapper that resolves `$`-prefixed token strings on `fill`, `stroke`, `stopColor`, and `color` attributes to live theme values. Any standard SVG attribute (`width`, `height`, `viewBox`, etc.) is accepted via `SVGProps<SVGSVGElement>`.

## Installation

```bash
npm install @xsolla/xui-svg-themed
```

## Imports

```tsx
import { SvgThemed, type SvgThemedProps } from "@xsolla/xui-svg-themed";
```

## Quick start

```tsx
import * as React from "react";
import { SvgThemed } from "@xsolla/xui-svg-themed";

export default function QuickStart() {
  return (
    <SvgThemed width={24} height={24} viewBox="0 0 24 24">
      <circle cx={12} cy={12} r={10} fill="$colors_core_text_primary" />
    </SvgThemed>
  );
}
```

## API Reference

### `<SvgThemed>`

| Prop          | Type        | Default | Description                                                                                                   |
| ------------- | ----------- | ------- | ------------------------------------------------------------------------------------------------------------- |
| `children`    | `ReactNode` | —       | SVG content. Themed token strings are resolved recursively.                                                   |
| `data-testid` | `string`    | —       | Test identifier.                                                                                              |
| `testID`      | `string`    | —       | Test ID for testing frameworks. On web this renders as `data-testid`; on React Native it renders as `testID`. |

Standard SVG attributes (`width`, `height`, `viewBox`, `xmlns`, `role`, `fill`, `stroke`, etc.) come from `SVGProps<SVGSVGElement>` and are forwarded to the underlying `<svg>` element — they are not enumerated as explicit props.

Inherits `ThemeOverrideProps` (`themeMode`, `themeProductContext`).

### Themeable attributes

The following descendant attributes are scanned recursively and replaced when their string value starts with `$`:

- `fill`
- `stroke`
- `stopColor`
- `color`

## Theming

Token strings start with `$` and map to theme paths. Tokens not in the map are passed through unchanged.

| Token                         | Theme path                  |
| ----------------------------- | --------------------------- |
| `$colors_core_text_primary`   | `content.primary`           |
| `$colors_core_text_secondary` | `content.secondary`         |
| `$colors_core_text_tertiary`  | `content.tertiary`          |
| `$colors_core_text_brand`     | `content.brand.primary`     |
| `$colors_core_text_success`   | `content.success.primary`   |
| `$colors_core_text_warning`   | `content.warning.primary`   |
| `$colors_core_text_alert`     | `content.alert.primary`     |
| `$colors_core_text_neutral`   | `content.neutral.primary`   |
| `$colors_control_faint_bg`    | `control.mono.secondary.bg` |

## Examples

### Themed status icon

```tsx
import * as React from "react";
import { SvgThemed } from "@xsolla/xui-svg-themed";

export default function StatusIcon() {
  return (
    <SvgThemed width={24} height={24} viewBox="0 0 24 24">
      <circle cx={12} cy={12} r={10} fill="$colors_core_text_success" />
      <path
        d="M8 12L11 15L16 9"
        stroke="#fff"
        strokeWidth={2}
        fill="none"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    </SvgThemed>
  );
}
```

### Multi-colour illustration

```tsx
import * as React from "react";
import { SvgThemed } from "@xsolla/xui-svg-themed";

export default function Illustration() {
  return (
    <SvgThemed width={100} height={100} viewBox="0 0 100 100">
      <rect width={100} height={100} rx={12} fill="$colors_control_faint_bg" />
      <circle cx={50} cy={40} r={20} fill="$colors_core_text_brand" />
      <rect
        x={30}
        y={65}
        width={40}
        height={20}
        rx={4}
        fill="$colors_core_text_secondary"
      />
    </SvgThemed>
  );
}
```

### Gradient with token stops

```tsx
import * as React from "react";
import { SvgThemed } from "@xsolla/xui-svg-themed";

export default function GradientBadge() {
  return (
    <SvgThemed width={48} height={48} viewBox="0 0 48 48">
      <defs>
        <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
          <stop offset="0%" stopColor="$colors_core_text_brand" />
          <stop offset="100%" stopColor="$colors_core_text_success" />
        </linearGradient>
      </defs>
      <circle cx={24} cy={24} r={20} fill="url(#grad)" />
    </SvgThemed>
  );
}
```

## Accessibility

- Pass `role="img"` and an `aria-label` (or `<title>` element) when the SVG conveys meaning.
- Set `aria-hidden="true"` for decorative graphics.
