# llms-full (private-aware)
> Built from GitHub files and website pages. Large files may be truncated.

--- src/Installation.mdx ---
import { Subtitle, Title, Meta } from "@storybook/blocks";
import { NextPrev } from "@storybookComponents/NextPrev"

<Meta title="Overview/Installation" />

<Title>Installation</Title>
<Subtitle>Quick tutorial for adding Apps SDK UI to your app</Subtitle>


## Prerequisites

Apps SDK UI is built on top of React and Tailwind 4. To use Apps SDK UI, you'll need to have both installed in your project, and configured with your build system.

- React 18 or 19 ([install guide](https://react.dev/learn/installation))
- Tailwind 4 ([install guide](https://tailwindcss.com/docs/installation))


## Install steps

### 1. Install the package

```bash
npm install @openai/apps-sdk-ui
```

### 2. Setup styles

Add the foundation styles and Tailwind layers to the top of your global stylesheet (e.g. `main.css`):

```css
@import "tailwindcss";
@import "@openai/apps-sdk-ui/css";
/* Required for Tailwind to find class references in Apps SDK UI components. */
@source "../node_modules/@openai/apps-sdk-ui";

/* The rest of your application CSS */
```

Then import your stylesheet *before* rendering any components:

```tsx
// Must be imported first to ensure Tailwind layers and style foundations are defined before any potential component styles
import "./main.css"

import { StrictMode } from "react"
import { createRoot } from "react-dom/client"
import { App } from "./App"

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <App />
  </StrictMode>,
)
```

### 3. Configure router (optional)

`<AppsSDKUIProvider>` helps define your default router link component, used in components like `<TextLink>` and `<ButtonLink>`.

 This provider is optional - router links can also be [passed directly to components](https://openai.github.io/apps-sdk-ui/?path=/docs/components-textlink--docs#component-level) via the `as` prop.

```tsx
// Must be imported first to ensure Tailwind layers and style foundations are defined before component styles
import "./main.css"

import { AppsSDKUIProvider } from "@openai/apps-sdk-ui/components/AppsSDKUIProvider"
import { StrictMode } from "react"
import { createRoot } from "react-dom/client"
import { Link } from 'react-router'
import { App } from "./App"

declare global {
  interface AppsSDKUIConfig {
    LinkComponent: typeof Link
  }
}

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <AppsSDKUIProvider linkComponent={Link}>
      <App />
    </AppsSDKUIProvider>
  </StrictMode>,
)
```

### Start building

Your project is now ready to use Apps SDK UI!

Here's an example of a simple reservation card, using Tailwind classes and components.

```tsx
import { Badge } from "@openai/apps-sdk-ui/components/Badge"
import { Button } from "@openai/apps-sdk-ui/components/Button"
import {
  Calendar,
  Invoice,
  Maps,
  Members,
  Phone,
} from "@openai/apps-sdk-ui/components/Icon"

export function ReservationCard() {
  return (
    <div className="w-full max-w-sm rounded-2xl border border-default bg-surface shadow-lg p-4">
      <div className="flex items-start justify-between gap-3">
        <div>
          <p className="text-secondary text-sm">
            Reservation
          </p>
          <h2 className="mt-1 heading-lg">La Luna Bistro</h2>
        </div>
        <Badge color="success">Confirmed</Badge>
      </div>
      <div>
        <dl className="mt-4 grid grid-cols-[auto_1fr] gap-x-3 gap-y-2 text-sm">
          <dt className="flex items-center gap-1.5 font-medium text-secondary">
            <Calendar className="size-4" />
            Date
          </dt>
          <dd className="text-right">Apr 12 · 7:30 PM</dd>
          <dt className="flex items-center gap-1.5 font-medium text-secondary">
            <Members className="size-4" />
            Guests
          </dt>
          <dd className="text-right">Party of 2</dd>
          <dt className="flex items-center gap-1.5 font-medium text-secondary">
            <Invoice className="size-4" />
            Reference
          </dt>
          <dd className="text-right uppercase">4F9Q2K</dd>
        </dl>
      </div>
      <div className="mt-4 grid gap-3 border-t border-subtle pt-4 sm:grid-cols-2">
        <Button variant="soft" color="secondary" block>
          <Phone />
          Call
        </Button>
        <Button color="primary" block>
          <Maps />
          Directions
        </Button>
      </div>
    </div>
  )
}
```


<NextPrev
  prev={{title: 'Introduction', path: 'overview-introduction' }}
  next={{title: 'Dark mode', path: 'concepts-dark-mode' }}
/>


## Links discovered
- [install guide](https://react.dev/learn/installation)
- [install guide](https://tailwindcss.com/docs/installation)
- [passed directly to components](https://openai.github.io/apps-sdk-ui/?path=/docs/components-textlink--docs#component-level)

--- src/components/AppsSDKUIProvider/internal.ts ---
"use client"

import { useContext } from "react"
import { AppsSDKUIContext } from "./AppsSDKUIContext"

export function useLinkComponent() {
  const context = useContext(AppsSDKUIContext)
  return context?.linkComponent ?? "a"
}


--- AGENTS.md ---
# Contribution guide for Apps SDK UI

Apps SDK UI is a design system tailored for building apps in ChatGPT. Apps SDK UI provides styling foundations, CSS variable design tokens, and a library of well-crafted, accessible components.

- **Design tokens** – defined across colors, typography, spacing, sizing, shadows, surfaces, and more.
- **Tailwind 4** – fully integrated and pre-configured with Apps SDK UI's design tokens.
- **Component library** – high-quality components built on top of Radix for consistent accessibility patterns.
- **Utilities** – helpful tools for handling core concepts like dark mode, responsiveness, and more across React and CSS.

Keep this goal and context in mind as you contribute code to the repository. This code is the foundation for many other projects, and changes should be robust, well-considered, and workable for many different contexts.

## Repository overview

You should make changes only in the `src/` folder:

- `components/` - React component implementations (e.g., Button, Chat, Tooltip)
- `hooks/` - Reusable React hooks (e.g., useAutoGrowTextarea, useBreakpoints)
- `lib/` - Utility functions (theme helpers, attachment helpers, etc.)
- `styles/` - Global CSS config, Tailwind setup, and design token definitions
- `**/*.stories.tsx` - Storybook stories definition for a given component
- `**/*.mdx` - Storybook documentation, often referring to sibling `.stories.tsx` file
- `types.ts` - Shared TypeScript types
- `vite-env.d.ts` - Vite type declarations

When adding new functionality or docs, place files in the appropriate `src/*` location.

# Components

## File Naming Conventions

- Component: `ComponentName.tsx`
- Styles: `ComponentName.module.css`
- Tests: `ComponentName.test.tsx`
- Storybook:
  - `ComponentName.stories.tsx`
  - `ComponentName.mdx`

## Component library

Below is a quick reference of all provided components:

| Component              | Description                                                           |
| ---------------------- | --------------------------------------------------------------------- |
| **Alert**              | Call attention to a specific message or warning.                      |
| **Animate**            | Animate components as they mount and unmount.                         |
| **AnimateLayout**      | Animate width & height of components as they mount and unmount.       |
| **AnimateLayoutGroup** | Animate width & height of lists of components as they enter and exit. |
| **Avatar**             | Display user identities with either text, photo, or an icon.          |
| **AvatarGroup**        | Display avatars as a single stack.                                    |
| **Badge**              | Emphasize details with a status indicator.                            |
| **Button**             | Create actions in many different styles.                              |
| **ButtonLink**         | `<Button>` but as a semantic anchor element.                          |
| **Checkbox**           | Toggle control for on and off states.                                 |
| **CodeBlock**          | Display syntax‑highlighted code snippets.                             |
| **CopyTooltip**        | Allow users to easily copy to clipboard.                              |
| **EmptyMessage**       | Gracefully inform users when there's nothing to see.                  |
| **Icon**               | Collection of SVG icons exported as React components.                 |
| **Image**              | Load remote images with optional aspect ratio and cover mode.         |
| **Indicator**          | Loading dots and circular progress indicators.                        |
| **Input**              | Semantic input text collection.                                       |
| **Markdown**           | Render rich formatted content.                                        |
| **Menu**               | Structured actions in a dropdown list.                                |
| **Modal**              | Capture focus for essential tasks or details.                         |
| **AppsSDKUIProvider**  | React provider for shared context (e.g., link component).             |
| **Popover**            | Generic floating UI utility for contextual actions.                   |
| **RadioGroup**         | Radio button group selection component.                               |
| **SegmentedControl**   | Toggle through grouped options.                                       |
| **Select**             | Choose from a dropdown of options.                                    |
| **SelectControl**      | Alternative select control component with enhanced features.          |
| **Slider**             | Fine-tune values within a set range.                                  |
| **Switch**             | Toggle control for on and off states.                                 |
| **TagInput**           | Enter multiple unique tags.                                           |
| **TextLink**           | Semantic link used for both internal and external links.              |
| **Textarea**           | Autosizable text input area with optional validation.                 |
| **Tooltip**            | Brief and informative hover text.                                     |
| **TransitionGroup**    | Primitive for rendering components over time.                         |

## Documentation & Storybook

All components should be thoroughly documented in Storybook, using the `.mdx` and `.stories` sidecar files.

- You should not need to run Storybook locally, so ignore the `pnpm run storybook` command
- Update or create `.mdx` and `.stories.tsx` files when adding new components or features.
- Keep usage examples simple and focused. Refer to documentation examples like `Avatar`, `Badge`, and `Button` for guidance.

# Contributing

When working on features or documentation, avoid making unrelated changes to the current task. Do not add comments for obvious behaviors, and do not change build settings.

## Setup instructions

- Use Node version specified in `.node-version`
- Install dependencies with `npm install`

## Required commands before commit

1. `npm run format:fix` - Auto-fixes any formatting issues
2. `npm run lint` - Runs ESLint (TS) and Stylelint (CSS)
3. `npm run types` - Runs TypeScript type checking
4. `npm run test` - Executes unit tests via Vitest

Ignore all other script commands, as they will be irrelevant to your work.


--- README.md ---
# Apps SDK UI

Apps SDK UI is a lightweight, accessible design system for building high-quality ChatGPT apps with the [Apps SDK](https://developers.openai.com/apps-sdk). It provides Tailwind-integrated design tokens, a curated React component library, and utilities optimized for consistent experiences inside ChatGPT.

## Features

- **Design tokens** for colors, typography, spacing, sizing, shadows, surfaces, and more.
- **Tailwind 4 integration** pre-configured with Apps SDK UI's design tokens.
- **Accessible components**, built on Radix primitives with consistent styling.
- **Utilities** for dark mode, responsive layouts, and ChatGPT-optimized behaviors.
- **Minimal boilerplate** — import styles, wrap with a provider, start building.

## Prerequisites

Apps SDK UI requires **React 18 or 19** and **Tailwind 4**.

- React: https://react.dev/learn/installation
- Tailwind 4: https://tailwindcss.com/docs/installation

## Installation

### 1. Install the package

```bash
npm install @openai/apps-sdk-ui
```

### 2. Setup styles

Add the foundation styles and Tailwind layers to the top of your global stylesheet (e.g. `main.css`):

```css
@import "tailwindcss";
@import "@openai/apps-sdk-ui/css";
/* Required for Tailwind to find class references in Apps SDK UI components. */
@source "../node_modules/@openai/apps-sdk-ui";

/* The rest of your application CSS */
```

Then import your stylesheet _before_ rendering any components:

```tsx
// Must be imported first to ensure Tailwind layers and style foundations are defined before any potential component styles
import "./main.css"

import { StrictMode } from "react"
import { createRoot } from "react-dom/client"
import { App } from "./App"

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <App />
  </StrictMode>,
)
```

### 3. Configure router (optional)

`<AppsSDKUIProvider>` helps define your default router link component, used in components like `<TextLink>` and `<ButtonLink>`.

This provider is optional - router links can also be [passed directly to components](https://openai.github.io/apps-sdk-ui/?path=/docs/components-textlink--docs#component-level) via the `as` prop.

```tsx
// Must be imported first to ensure Tailwind layers and style foundations are defined before component styles
import "./main.css"

import { AppsSDKUIProvider } from "@openai/apps-sdk-ui/components/AppsSDKUIProvider"
import { StrictMode } from "react"
import { createRoot } from "react-dom/client"
import { Link } from "react-router"
import { App } from "./App"

declare global {
  interface AppsSDKUIConfig {
    LinkComponent: typeof Link
  }
}

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <AppsSDKUIProvider linkComponent={Link}>
      <App />
    </AppsSDKUIProvider>
  </StrictMode>,
)
```

### Start building

Your project is now ready to use Apps SDK UI!

Here's an example of a simple reservation card, using Tailwind classes and components.

```tsx
import { Badge } from "@openai/apps-sdk-ui/components/Badge"
import { Button } from "@openai/apps-sdk-ui/components/Button"
import { Calendar, Invoice, Maps, Members, Phone } from "@openai/apps-sdk-ui/components/Icon"

export function ReservationCard() {
  return (
    <div className="w-full max-w-sm rounded-2xl border border-default bg-surface shadow-lg p-4">
      <div className="flex items-start justify-between gap-3">
        <div>
          <p className="text-secondary text-sm">Reservation</p>
          <h2 className="mt-1 heading-lg">La Luna Bistro</h2>
        </div>
        <Badge color="success">Confirmed</Badge>
      </div>
      <div>
        <dl className="mt-4 grid grid-cols-[auto_1fr] gap-x-3 gap-y-2 text-sm">
          <dt className="flex items-center gap-1.5 font-medium text-secondary">
            <Calendar className="size-4" />
            Date
          </dt>
          <dd className="text-right">Apr 12 · 7:30 PM</dd>
          <dt className="flex items-center gap-1.5 font-medium text-secondary">
            <Members className="size-4" />
            Guests
          </dt>
          <dd className="text-right">Party of 2</dd>
          <dt className="flex items-center gap-1.5 font-medium text-secondary">
            <Invoice className="size-4" />
            Reference
          </dt>
          <dd className="text-right uppercase">4F9Q2K</dd>
        </dl>
      </div>
      <div className="mt-4 grid gap-3 border-t border-subtle pt-4 sm:grid-cols-2">
        <Button variant="soft" color="secondary" block>
          <Phone />
          Call
        </Button>
        <Button color="primary" block>
          <Maps />
          Directions
        </Button>
      </div>
    </div>
  )
}
```

## License

[MIT](LICENSE) © OpenAI


## Links discovered
- [Apps SDK](https://developers.openai.com/apps-sdk)
- [passed directly to components](https://openai.github.io/apps-sdk-ui/?path=/docs/components-textlink--docs#component-level)
- [MIT](https://github.com/openai/apps-sdk-ui/blob/main/LICENSE.md)

--- happydom.ts ---
import { GlobalRegistrator } from "@happy-dom/global-registrator"

GlobalRegistrator.register()


--- matchers.d.ts ---
/* eslint-disable */
import type { TestingLibraryMatchers } from "@testing-library/jest-dom/matchers"
import type { ExpectStatic } from "vitest"

declare module "vitest" {
  interface Assertion<T = any>
    extends TestingLibraryMatchers<ExpectStatic["stringContaining"], T> {}
  interface AsymmetricMatchers extends TestingLibraryMatchers {}
}


--- prettier.config.js ---
/**
 * @type {import('prettier').Options}
 */
module.exports = {
  printWidth: 100,
  quoteProps: "consistent",
  semi: false,
  plugins: [
    require.resolve("prettier-plugin-tailwindcss"),
    require.resolve("prettier-plugin-organize-imports"),
  ],
  tailwindFunctions: ["clsx"],
  tabWidth: 2,
}


--- testing-library.ts ---
import * as matchers from "@testing-library/jest-dom/matchers"
import { cleanup } from "@testing-library/react"
import { afterEach, expect } from "vitest"

expect.extend(matchers)

// Optional: cleans up `render` after each test
afterEach(() => {
  cleanup()
})


--- vitest.config.ts ---
import { resolve } from "node:path"

import react from "@vitejs/plugin-react"
import { defineConfig } from "vitest/config"

export default defineConfig(async () => {
  const { default: tsconfigPaths } = await import("vite-tsconfig-paths")

  return {
    resolve: {
      alias: {
        "@": resolve(__dirname, "src"),
      },
    },
    plugins: [react(), tsconfigPaths({ root: __dirname })],
    test: {
      environment: "happy-dom",
      setupFiles: ["./happydom.ts", "./testing-library.ts", "./test/setupTests.ts"],
      include: [
        "src/**/*.test.{ts,tsx}",
        "test/**/*.test.{ts,tsx}",
        "postcss/**/*.test.{js,mjs,ts}",
      ],
    },
  }
})


--- .storybook-base/main.ts ---
import type { StorybookConfig } from "@storybook/react-vite"
import path from "path"

const config: StorybookConfig = {
  stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-toolbars",
    {
      name: "@storybook/addon-essentials",
      // Disable subpar features that create more noise than signal
      options: {
        actions: false,
        backgrounds: false,
        viewport: false,
        toolbars: false,
        measure: false,
        outline: false,
        highlight: false,
      },
    },
    {
      name: "@storybook/addon-storysource",
      options: {
        loaderOptions: {
          prettierConfig: {
            printWidth: 90,
            useTabs: false,
            semi: false,
            tabWidth: 2,
          },
        },
      },
    },
  ],
  typescript: {
    reactDocgen: "react-docgen-typescript",
    reactDocgenTypescriptOptions: {
      savePropValueAsString: true,
      shouldRemoveUndefinedFromOptional: true,
      shouldExtractLiteralValuesFromEnum: true,
    },
  },
  framework: {
    name: "@storybook/react-vite",
    options: {
      builder: {
        viteConfigPath: "./vite.config.mjs",
      },
    },
  },
  staticDirs: ["../public"],
  async viteFinal(finalConfig) {
    process.env.IS_STORYBOOK = "true"

    // Allow imports from `.storybook/components` directory in our MDX files
    finalConfig.resolve = finalConfig.resolve || { alias: {} }
    finalConfig.resolve.alias = {
      ...finalConfig.resolve.alias,
      "@storybookComponents": path.resolve(__dirname, "./components/"),
    }

    // https://github.com/storybookjs/storybook/issues/25256
    finalConfig.assetsInclude = ["/sb-preview/runtime.js"]

    // Storybook fails when `verbatimModuleSyntax` is true, so override the
    // compiler option specifically for this build.
    finalConfig.esbuild = finalConfig.esbuild || {}
    finalConfig.esbuild.tsconfigRaw = {
      compilerOptions: {
        verbatimModuleSyntax: false,
      },
    }

    return finalConfig
  },
}
export default config


--- .storybook-base/manager.ts ---
import { addons } from "@storybook/manager-api"
import { init as initThemeAddon } from "./addon-theme"

import "./addon-back-to-docs"
import "./addon-title"
import "./addon-toggle-addons"

addons.setConfig({
  navSize: 230,
  toolbar: {
    copy: { hidden: true },
    eject: { hidden: true },
    fullscreen: { hidden: true },
    createStory: { hidden: true },
  },
  sidebar: {
    showRoots: true,
    collapsedRoots: [],
  },
  docs: {
    isCodeExpanded: true,
    source: {
      state: "shown",
    },
  },
})

// Manually initialize local addons
initThemeAddon()

addons.register("view-mode", (api) => {
  const channel = addons.getChannel()

  const setAttr = (mode: "story" | "docs") =>
    document.documentElement.setAttribute("data-view-mode", mode)

  setAttr(api.getUrlState().viewMode === "docs" ? "docs" : "story")

  channel.on("docsRendered", () => setAttr("docs"))
  channel.on("storyRendered", () => {
    const { viewMode } = api.getUrlState() // 'story' | 'docs' | custom tabs :contentReference[oaicite:0]{index=0}
    setAttr(viewMode === "docs" ? "docs" : "story")
  })
})


--- .storybook-base/manager-head.html ---
<link rel="icon" type="image/png" href="/favicon-storybook.png" />
<link rel="icon" type="image/svg+xml" href="/favicon-storybook.svg" />
<link rel="preconnect" href="https://cdn.openai.com" />

<style>
  :root {
    --gray-0: light-dark(#ffffff, #0d0d0d);
    --gray-25: light-dark(#fcfcfc, #101010);
    --gray-50: light-dark(#f9f9f9, #131313);
    --gray-75: light-dark(#f3f3f3, #161616);
    --gray-100: light-dark(#ededed, #181818);
    --gray-150: light-dark(#dfdfdf, #1c1c1c);
    --gray-200: light-dark(#c4c4c4, #212121);
    --gray-250: light-dark(#b9b9b9, #292929);
    --gray-300: light-dark(#afafaf, #303030);
    --gray-350: light-dark(#9f9f9f, #393939);
    --gray-400: light-dark(#8f8f8f, #414141);
    --gray-450: light-dark(#767676, #4f4f4f);
    --gray-500: #5d5d5d;
    --gray-550: light-dark(#4f4f4f, #767676);
    --gray-600: light-dark(#414141, #8f8f8f);
    --gray-650: light-dark(#393939, #9f9f9f);
    --gray-700: light-dark(#303030, #afafaf);
    --gray-750: light-dark(#292929, #b9b9b9);
    --gray-800: light-dark(#212121, #c4c4c4);
    --gray-850: light-dark(#1c1c1c, #dcdcdc);
    --gray-900: light-dark(#181818, #ededed);
    --gray-925: light-dark(#161616, #f3f3f3);
    --gray-950: light-dark(#131313, #f3f3f3);
    --gray-975: light-dark(#101010, #f9f9f9);
    --gray-1000: light-dark(#0d0d0d, #ffffff);
    --alpha-base: light-dark(#0d0d0d, #ffffff);
    --alpha-0: color-mix(in srgb, var(--alpha-base) 0%, transparent);
    --alpha-02: color-mix(in srgb, var(--alpha-base) 2%, transparent);
    --alpha-04: color-mix(in srgb, var(--alpha-base) 4%, transparent);
    --alpha-05: color-mix(in srgb, var(--alpha-base) 5%, transparent);
    --alpha-06: color-mix(in srgb, var(--alpha-base) 6%, transparent);
    --alpha-08: color-mix(in srgb, var(--alpha-base) 8%, transparent);
    --alpha-10: color-mix(in srgb, var(--alpha-base) 10%, transparent);
    --alpha-12: color-mix(in srgb, var(--alpha-base) 12%, transparent);
    --alpha-15: color-mix(in srgb, var(--alpha-base) 15%, transparent);
    --alpha-20: color-mix(in srgb, var(--alpha-base) 20%, transparent);
    --alpha-25: color-mix(in srgb, var(--alpha-base) 25%, transparent);
    --alpha-30: color-mix(in srgb, var(--alpha-base) 30%, transparent);
    --alpha-35: color-mix(in srgb, var(--alpha-base) 35%, transparent);
    --alpha-40: color-mix(in srgb, var(--alpha-base) 40%, transparent);
    --alpha-50: color-mix(in srgb, var(--alpha-base) 50%, transparent);

    --sb-input-border-color: light-dark(rgba(0, 0, 0, 0.08), rgba(255, 255, 255, 0.18));
    --sb-input-border-hover-color: light-dark(rgba(0, 0, 0, 0.15), rgba(255, 255, 255, 0.25));
    --sb-input-border-focus-color: light-dark(rgba(0, 0, 0, 0.25), rgba(255, 255, 255, 0.35));
    --color-text: light-dark(var(--gray-750), var(--gray-850));
    --color-text-secondary: light-dark(var(--gray-500), var(--gray-700));
    --color-surface: light-dark(var(--gray-0), var(--gray-200));
  }

  /* When the document doesn't know its theme, keep it hidden */
  html:not([data-theme]),
  /* When the story iframe itself is still loading */
  [data-is-loaded="false"] {
    visibility: hidden;
  }

  * {
    /* Aesthetic scrollbar defaults */
    scrollbar-color: var(--alpha-30) transparent;
    scrollbar-width: thin;
  }

  .sidebar-header {
    margin-top: -6px !important;
  }

  .sidebar-header a {
    pointer-events: none;
  }

  .sidebar-header a:focus {
    outline: 0;
  }

  /* Hide the gear icon */
  .sidebar-header > div:last-child {
    display: none !important;
  }

  /* Hide the "Create new story" button */
  .search-field + div {
    display: none;
  }

  /* Hide resize handlebar */
  div:has(+ .sidebar-container) {
    display: none;
  }

  /* Search box */
  .search-field {
    position: relative;
    margin-top: -6px !important;
    height: 36px !important;
    box-shadow: 0 0 0 1px var(--sb-input-border-color) !important;
    transition: box-shadow 0.15s ease;
  }

  .search-field::before {
    content: "";
    -webkit-mask-image: linear-gradient(0deg, rgba(0, 0, 0, 0), rgb(0, 0, 0));
    mask-image: linear-gradient(0deg, rgba(0, 0, 0, 0), #000);
    height: 20px;
    position: absolute;
    top: 100%;
    right: 0;
    left: 0;
    z-index: 2;
    margin-top: 1px;
    background: var(--color-surface);
    pointer-events: none;
  }

  .search-field:hover {
    box-shadow: 0 0 0 1px var(--sb-input-border-hover-color) !important;
  }
  .search-field:has(#storybook-explorer-searchfield:focus) {
    box-shadow: 0 0 0 1px var(--sb-input-border-focus-color) !important;
  }
  #storybook-explorer-searchfield {
    font-size: 14px !important;
  }
  /* Hide tags filter */
  .search-field > div:last-child > div {
    display: none !important;
  }

  .search-field > div:last-child > button {
    width: 22px;
    height: 22px;
    padding: 0;
    margin-right: 4px;
    border-radius: 100%;
  }

  .search-field > div:last-child > button:hover {
    background: light-dark(var(--gray-100), var(--gray-400)) !important;
    color: var(--gray-900) !important;
  }

  .search-result-recentlyOpened {
    color: light-dark(var(--gray-400), var(--gray-650)) !important;
    text-transform: none !important;
    letter-spacing: 0em !important;
    font-size: 14px !important;
    font-weight: 500 !important;
    margin-top: 0 !important;
    margin-bottom: 4px !important;
    padding-left: 10px !important;
  }

  /* Search results */
  .search-result-item {
    margin-bottom: 2px !important;
    padding: 8px 10px !important;
    background-color: transparent !important;
    border-radius: 6px !important;
  }

  .search-result-item:hover {
    background: light-dark(var(--gray-100), var(--gray-400)) !important;
  }

  .search-result-item > div:first-child {
    display: none !important;
  }

  .search-result-item--label > div:first-child {
    margin-bottom: 2px !important;
    font-size: 14px !important;
    font-weight: 500 !important;
    color: var(--color-text) !important;
  }

  .search-result-item--label > div:first-child mark {
    color: var(--color-text) !important;
    background: var(--alpha-08) !important;
  }

  .search-result-item--label > div:last-child {
    color: light-dark(var(--gray-500), var(--gray-650)) !important;
    font-size: 12px !important;
  }

  .story-back-link {
    position: absolute;
    top: 5px;
    left: 16px;
  }

  /* panel */
  #root > div > div:nth-child(3):not(:has(.sidebar-container)) {
    margin-right: 20px;
    margin-left: 20px;
    border: 1px solid var(--gray-150);
    border-bottom: 0;
    border-radius: 8px 8px 0 0;
  }

  #root > div > div:nth-child(3):not(:has(.sidebar-container)) div[orientation]::after,
  #root > div > div:nth-child(3):not(:has(.sidebar-container)) .sb-bar {
    background: none;
  }

  #root
    > div
    > div:nth-child(3):not(:has(.sidebar-container))
    [title="Change addon orientation [⌥ D]"] {
    display: none !important;
  }

  /* Sidebar container */
  #root > div > div:nth-child(2),
  #root > div > div:nth-child(3):has(.sidebar-container) {
    border: 0 !important;
  }

  /* Sidebar custom nested scroll */
  #storybook-explorer-menu {
    position: absolute;
    top: 99px;
    left: 0;
    right: 0;
    bottom: 0;
    overflow: auto;
    margin: 0;
    padding: 20px 12px 10px;
  }

  /* Sidebar "Roots" - remove expand/collapse and treat as normal headers */
  [data-nodetype="root"] {
    pointer-events: none !important;
    color: light-dark(var(--gray-400), var(--gray-650)) !important;
    text-transform: none !important;
    letter-spacing: 0em !important;
    font-size: 14px !important;
    font-weight: 500 !important;
    margin-top: 0px !important;
    margin-bottom: 4px !important;
  }

  .sidebar-item ~ [data-nodetype="root"] {
    margin-top: 20px !important;
  }

  [data-nodetype="root"] button:first-child {
    padding-left: 10px !important;
  }

  [data-nodetype="root"] button:first-child > div:first-child {
    display: none;
  }

  [data-nodetype="root"] .sidebar-subheading-action {
    display: none;
  }

  /* Sidebar spacing nudges */
  .sidebar-item {
    min-height: auto !important;
    margin-bottom: 2px !important;
    border-radius: 6px !important;
    font-weight: 500 !important;
    transition: background-color 0.1s ease;
  }
  .sidebar-item:not([data-selected="true"]):hover {
    background: light-dark(var(--gray-100), var(--gray-400)) !important;
  }
  .sidebar-item > button {
    align-items: center !important;
  }
  .sidebar-item > button > div {
    margin-top: 0 !important;
  }
  .sidebar-item > button:first-child {
    padding-top: 4px !important;
  }
  .sidebar-item > a:first-child {
    min-height: 36px !important;
    align-items: center !important;
    padding: 0 0 0 10px !important;
    font-weight: inherit !important;
    color: var(--color-text) !important;
  }
  .sidebar-item > a:first-child > div {
    display: none !important;
    margin-top: 1px;
  }
  .sidebar-item[data-selected="true"] {
    background: light-dark(var(--gray-100), var(--gray-400)) !important;
    color: var(--gray-900) !important;
    font-weight: 600 !important;
  }

  /* Story args table */
  .docblock-argstable-body td table {
    /* Hide JSDoc tables which are meant for IDE's and not Storybook */
    display: none !important;
  }

  /* Toolbar */
  @media (min-width: 600px) {
    [data-test-id="sb-preview-toolbar"] {
      position: absolute !important;
      top: 0 !important;
      left: 0 !important;
      background: transparent !important;
      box-shadow: none !important;
      pointer-events: none !important;
    }

    [data-test-id="sb-preview-toolbar"] button {
      pointer-events: all !important;
    }

    [data-view-mode="story"] [data-test-id="sb-preview-toolbar"] {
      position: static !important;
      pointer-events: all !important;
    }
  }

  @media (max-width: 599px) {
    #root > div > div:last-child {
      position: absolute !important;
      background: none !important;
    }

    #root > div > div:last-child > div > button {
      position: fixed;
      top: 8px;
      left: 8px;
      cursor: pointer;
    }

    #root > div > div:last-child > div > button svg {
      width: 22px;
      height: 22px;
    }

    #root > div > div:last-child > div > button p {
      display: none;
    }

    /* Hide addons drawer on mobile */
    #root > div > div:nth-child(3) {
      border: 0 !important;
    }

    #root > div > div:nth-child(3) button[title="Open addon panel"] {
      display: none !important;
    }

    .story-back-link {
      position: static !important;
    }
  }

  [data-test-id="sb-preview-toolbar"] > div {
    justify-content: flex-end !important;
    width: 100%;
    margin: 0 !important;
    padding: 0 8px;
  }

  [data-test-id="sb-preview-toolbar"] > div > div:last-child {
    display: none !important;
  }

  /* Toolbar hide orphan divider */
  .sb-bar > div > div > span:first-child {
    display: none !important;
  }

  #storybook-preview-iframe {
    opacity: 0 !important;
  }
  #storybook-preview-iframe[data-is-loaded="true"] {
    opacity: 1 !important;
  }
</style>


--- .storybook-base/addon-theme/constants.ts ---
export type Theme = "light" | "dark"
export const DEFAULT_THEME: Theme = "light"


--- .storybook-base/addon-title/index.ts ---
import { addons } from "@storybook/manager-api"

// SOURCE: https://github.com/storybookjs/storybook/issues/6339

addons.register("TitleAddon", (api) => {
  const STORYBOOK_TITLE = "Apps SDK UI"

  const setTitle = () => {
    let sectionTitle = ""
    try {
      const storyData = api.getCurrentStoryData()
      // Grab the last piece of the title, which will exclude section headings (e.g., Overview, Concepts, Components)
      const pageTitleArr = storyData.title.split("/")
      sectionTitle = pageTitleArr[storyData.depth - 1]

      // Add story suffix, if present
      if (storyData.type === "story") {
        sectionTitle += `/${storyData.name}`
      }
    } catch (e) {
      // do nothing
    }

    document.title = sectionTitle ? `${sectionTitle} - ${STORYBOOK_TITLE}` : STORYBOOK_TITLE
  }

  return new MutationObserver(() => {
    if (document.title.endsWith("Storybook")) {
      setTitle()
    }
  }).observe(document.querySelector("title")!, {
    childList: true,
    subtree: true,
    characterData: true,
  })
})


--- .storybook-base/addon-theme/themes.ts ---
import { create, themes, type ThemeVars } from "@storybook/theming"
import { type Theme } from "./constants"

const light = create({
  base: "light",
  // Logo
  brandTitle: "Apps SDK UI",
  brandImage: "https://openai.github.io/apps-sdk-ui/logo-storybook.svg",
  brandUrl: "https://developers.openai.com",
  brandTarget: "_self",

  // Typography
  fontBase: `ui-sans-serif, -apple-system, system-ui, "Segoe UI", "Noto Sans", "Helvetica",
    "Arial", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif`,
  fontCode: `ui-monospace, "SFMono-Regular", "SF Mono", "Menlo", "Monaco", "Consolas",
    "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace`,

  // Variables
  colorPrimary: "#3A10E5",
  colorSecondary: "#585C6D",

  // UI
  appBg: "#ffffff",
  appContentBg: "#ffffff",
  appPreviewBg: "#ffffff",
  appBorderColor: "#ededed",
  appBorderRadius: 6,

  // Toolbar default and active colors
  barTextColor: "#6e6e80",
  barBg: "#ffffff",
})

const dark = create({
  ...themes.dark,
  // Logo
  brandTitle: "Apps SDK UI",
  brandImage: "https://openai.github.io/apps-sdk-ui/logo-storybook-dark.svg",
  brandUrl: "https://platform.openai.com",
  brandTarget: "_self",

  // Typography
  fontBase: `ui-sans-serif, -apple-system, system-ui, "Segoe UI", "Noto Sans", "Helvetica",
    "Arial", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif`,
  fontCode: `ui-monospace, "SFMono-Regular", "SF Mono", "Menlo", "Monaco", "Consolas",
    "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace`,

  // Variables
  colorPrimary: "#3A10E5",
  colorSecondary: "#585C6D",

  // UI
  appBg: "#212121",
  appContentBg: "#212121",
  appPreviewBg: "#212121",
  appBorderColor: "#393939",
  appBorderRadius: 6,

  // Toolbar default and active colors
  barTextColor: "#c1c1c1",
  barBg: "#212121",
})

export const THEMES: Record<Theme, ThemeVars> = {
  light,
  dark,
}


--- .storybook-base/addon-theme/themeStore.ts ---
export type { Theme } from "./constants"
import { DEFAULT_THEME, type Theme } from "./constants"

const STORAGE_KEY = "sb-addon-oai-theme-1"

const getThemeFromUrl = (urlString: string): string | null => {
  const url = new URL(urlString)
  const params = url.searchParams
  const globals = params.get("globals")
  if (globals) {
    const pairs = globals.split(";")
    for (const pair of pairs) {
      const [key, value] = pair.split(":")
      if (key === "theme") {
        return value
      }
    }
  }
  return null
}

export const setThemeStore = (theme: Theme) => {
  window.localStorage.setItem(STORAGE_KEY, theme)
}

export const getThemeStore = (): Theme => {
  const themeFromURL = getThemeFromUrl(window.location.href)
  if (themeFromURL === "light" || themeFromURL === "dark") {
    setThemeStore(themeFromURL)
    return themeFromURL
  }

  const themeFromStorage = window.localStorage.getItem(STORAGE_KEY) as Theme | undefined
  return themeFromStorage || DEFAULT_THEME
}

export const applyManagerThemeClass = (nextTheme: Theme) => {
  const htmlTag = document.documentElement
  htmlTag.setAttribute("data-theme", nextTheme)
  htmlTag.style.colorScheme = nextTheme
}


--- .storybook-base/components/tokens.ts ---
export const TEXT_COLORS = [
  // Base
  {
    type: "color",
    name: "color-text",
    value: {
      light: "var(--gray-1000)",
      dark: "var(--gray-1000)",
    },
  },

  // Secondary
  {
    type: "color",
    name: "color-text-secondary",
    value: {
      light: "var(--gray-500)",
      dark: "var(--gray-700)",
    },
  },

  // Tertiary
  {
    type: "color",
    name: "color-text-tertiary",
    value: {
      light: "var(--gray-400)",
      dark: "var(--gray-600)",
    },
  },

  // Inverse
  {
    type: "color",
    name: "color-text-inverse",
    value: {
      light: "var(--gray-0)",
      dark: "var(--gray-0)",
    },
  },
]

export const SEMANTIC_COLORS_PRIMARY = [
  // Text
  {
    type: "color",
    name: "color-text-primary",
    value: {
      light: "var(--gray-1000)",
      dark: "var(--gray-1000)",
    },
  },

  // Soft
  {
    type: "color",
    name: "color-background-primary-soft",
    value: {
      light: "var(--gray-100)",
      dark: "var(--gray-300)",
    },
  },
  {
    type: "color",
    name: "color-background-primary-soft-hover",
    value: {
      light: "var(--gray-150)",
      dark: "var(--gray-350)",
    },
  },
  {
    type: "color",
    name: "color-background-primary-soft-active",
    value: {
      light: "var(--gray-200)",
      dark: "var(--gray-400)",
    },
  },
  {
    type: "color",
    name: "color-background-primary-soft-alpha",
    value: {
      light: "var(--alpha-08)",
      dark: "var(--alpha-12)",
    },
  },
  {
    type: "color",
    name: "color-background-primary-soft-alpha-hover",
    value: {
      light: "var(--alpha-12)",
      dark: "var(--alpha-16)",
    },
  },
  {
    type: "color",
    name: "color-background-primary-soft-alpha-active",
    value: {
      light: "var(--alpha-16)",
      dark: "var(--alpha-20)",
    },
  },
  {
    type: "color",
    name: "color-text-primary-soft",
    value: {
      light: "var(--color-text)",
      dark: "var(--color-text)",
    },
  },
  {
    type: "color",
    name: "color-background-primary-soft-alt",
    value: {
      light: "var(--alpha-02)",
      dark: "var(--alpha-02)",
    },
  },
  {
    type: "color",
    name: "color-border-primary-soft-alt",
    value: {
      light: "var(--alpha-06)",
      dark: "var(--alpha-06)",
    },
  },
  {
    type: "color",
    name: "color-text-primary-soft-alt",
    value: {
      light: "var(--color-text)",
      dark: "var(--color-text)",
    },
  },

  // Surface
  {
    type: "color",
    name: "color-background-primary-surface",
    value: {
      light: "var(--alpha-05)",
      dark: "var(--alpha-08)",
    },
  },
  {
    type: "color",
    name: "color-border-primary-surface",
    value: {
      light: "var(--alpha-05)",
      dark: "var(--alpha-08)",
    },
  },
  {
    type: "color",
    name: "color-text-primary-surface",
    value: {
      light: "var(--color-text)",
      dark: "var(--color-text)",
    },
  },

  // Solid
  {
    type: "color",
    name: "color-background-primary-solid",
    value: {
      light: "var(--gray-900)",
      dark: "var(--gray-950)",
    },
  },
  {
    type: "color",
    name: "color-background-primary-solid-hover",
    value: {
      light: "var(--gray-700)",
      dark: "var(--gray-900)",
    },
  },
  {
    type: "color",
    name: "color-background-primary-solid-active",
    value: {
      light: "var(--gray-600)",
      dark: "var(--gray-850)",
    },
  },
  {
    type: "color",
    name: "color-text-primary-solid",
    value: {
      light: "var(--white)",
      dark: "var(--white)",
    },
  },

  // Outline
  {
    type: "color",
    name: "color-background-primary-outline-hover",
    value: {
      light: "var(--alpha-02)",
      dark: "var(--alpha-04)",
    },
  },
  {
    type: "color",
    name: "color-background-primary-outline-active",
    value: {
      light: "var(--alpha-04)",
      dark: "var(--alpha-06)",
    },
  },
  {
    type: "color",
    name: "color-border-primary-outline",
    value: {
      light: "var(--alpha-16)",
      dark: "var(--alpha-25)",
    },
  },
  {
    type: "color",
    name: "color-border-primary-outline-hover",
    value: {
      light: "var(--alpha-20)",
      dark: "var(--alpha-30)",
    },
  },
  {
    type: "color",
    name: "color-text-primary-outline",
    value: {
      light: "var(--color-text)",
      dark: "var(--color-text)",
    },
  },
  {
    type: "color",
    name: "color-text-primary-outline-hover",
    value: {
      light: "var(--color-text)",
      dark: "var(--color-text)",
    },
  },

  // Ghost
  {
    type: "color",
    name: "color-background-primary-ghost-hover",
    value: {
      light: "var(--alpha-08)",
      dark: "var(--alpha-12)",
    },
  },
  {
    type: "color",
    name: "color-background-primary-ghost-active",
    value: {
      light: "var(--alpha-12)",
      dark: "var(--alpha-16)",
    },
  },
  {
    type: "color",
    name: "color-text-primary-ghost",
    value: {
      light: "var(--color-text)",
      dark: "var(--color-text)",
    },
  },
  {
    type: "color",
    name: "color-text-primary-ghost-hover",
    value: {
      light: "var(--color-text)",
      dark: "var(--color-text)",
    },
  },

  // Ring
  {
    type: "color",
    name: "color-ring-primary",
    value: {
      light: "var(--color-ring)",
      dark: "var(--color-ring)",
    },
  },
  {
    type: "color",
    name: "color-ring-primary-soft",
    value: {
      light: "var(--color-ring-primary)",
      dark: "var(--color-ring-primary)",
    },
  },
  {
    type: "color",
    name: "color-ring-primary-solid",
    value: {
      light: "var(--color-ring-primary)",
      dark: "var(--color-ring-primary)",
    },
  },
  {
    type: "color",
    name: "color-ring-primary-outline",
    value: {
      light: "var(--color-ring-primary)",
      dark: "var(--color-ring-primary)",
    },
  },
  {
    type: "color",
    name: "color-ring-primary-ghost",
    value: {
      light: "var(--color-ring-primary)",
      dark: "var(--color-ring-primary)",
    },
  },
]

export const SEMANTIC_COLORS_SECONDARY = [
  // Soft
  {
    type: "color",
    name: "color-background-secondary-soft",
    value: {
      light: "var(--gray-100)",
      dark: "var(--gray-300)",
    },
  },
  {
    type: "color",
    name: "color-background-secondary-soft-hover",
    value: {
      light: "var(--gray-150)",
      dark: "var(--gray-350)",
    },
  },
  {
    type: "color",
    name: "color-background-secondary-soft-active",
    value: {
      light: "var(--gray-200)",
      dark: "var(--gray-400)",
    },
  },
  {
    type: "color",
    name: "color-background-secondary-soft-alpha",
    value: {
      light: "var(--alpha-08)",
      dark: "var(--alpha-12)",
    },
  },
  {
    type: "color",
    name: "color-background-secondary-soft-alpha-hover",
    value: {
      light: "var(--alpha-12)",
      dark: "var(--alpha-16)",
    },
  },
  {
    type: "color",
    name: "color-background-secondary-soft-alpha-active",
    value: {
      light: "var(--alpha-16)",
      dark: "var(--alpha-20)",
    },
  },
  {
    type: "color",
    name: "color-text-secondary-soft",
    value: {
      light: "var(--color-text)",
      dark: "var(--color-text)",
    },
  },
  {
    type: "color",
    name: "color-background-secondary-soft-alt",
    value: {
      light: "var(--alpha-02)",
      dark: "var(--alpha-02)",
    },
  },
  {
    type: "color",
    name: "color-border-secondary-soft-alt",
    value: {
      light: "var(--alpha-06)",
      dark: "var(--alpha-06)",
    },
  },
  {
    type: "color",
    name: "color-text-secondary-soft-alt",
    value: {
      light: "var(--color-text)",
      dark: "var(--color-text)",
    },
  },

  // Solid
  {
    type: "color",
    name: "color-background-secondary-solid",
    value: {
      light: "var(--gray-500)",
      dark: "var(--gray-400)",
    },
  },
  {
    type: "color",
    name: "color-background-secondary-solid-hover",
    value: {
      light: "var(--gray-600)",
      dark: "var(--gray-450)",
    },
  },
  {
    type: "color",
    name: "color-background-secondary-solid-active",
    value: {
      light: "var(--gray-700)",
      dark: "var(--gray-500)",
    },
  },
  {
    type: "color",
    name: "color-text-secondary-solid",
    value: {
      light: "var(--white)",
      dark: "var(--white)",
    },
  },

  // Outline
  {
    type: "color",
    name: "color-background-secondary-outline-hover",
    value: {
      light: "var(--alpha-02)",
      dark: "var(--alpha-04)",
    },
  },
  {
    type: "color",
    name: "color-background-secondary-outline-active",
    value: {
      light: "var(--alpha-04)",
      dark: "var(--alpha-06)",
    },
  },
  {
    type: "color",
    name: "color-border-secondary-outline",
    value: {
      light: "var(--alpha-16)",
      dark: "var(--alpha-25)",
    },
  },
  {
    type: "color",
    name: "color-border-secondary-outline-hover",
    value: {
      light: "var(--alpha-20)",
      dark: "var(--alpha-30)",
    },
  },
  {
    type: "color",
    name: "color-text-secondary-outline",
    value: {
      light: "var(--color-text-secondary)",
      dark: "var(--color-text-secondary)",
    },
  },
  {
    type: "color",
    name: "color-text-secondary-outline-hover",
    value: {
      light: "var(--color-text)",
      dark: "var(--color-text)",
    },
  },

  // Ghost
  {
    type: "color",
    name: "color-background-secondary-ghost-hover",
    value: {
      light: "var(--alpha-08)",
      dark: "var(--alpha-12)",
    },
  },
  {
    type: "color",
    name: "color-background-secondary-ghost-active",
    value: {
      light: "var(--alpha-12)",
      dark: "var(--alpha-16)",
    },
  },
  {
    type: "color",
    name: "color-text-secondary-ghost",
    value: {
      light: "var(--color-text-secondary)",
      dark: "var(--color-text-secondary)",
    },
  },
  {
    type: "color",
    name: "color-text-secondary-ghost-hover",
    value: {
      light: "var(--color-text)",
      dark: "var(--color-text)",
    },
  },

  // Ring
  {
    type: "color",
    name: "color-ring-secondary",
    value: {
      light: "var(--color-ring)",
      dark: "var(--color-ring)",
    },
  },
  {
    type: "color",
    name: "color-ring-secondary-soft",
    value: {
      light: "var(--color-ring-secondary)",
      dark: "var(--color-ring-secondary)",
    },
  },
  {
    type: "color",
    name: "color-ring-secondary-solid",
    value: {
      light: "var(--color-ring-secondary)",
      dark: "var(--color-ring-secondary)",
    },
  },
  {
    type: "color",
    name: "color-ring-secondary-outline",
    value: {
      light: "var(--color-ring-secondary)",
      dark: "var(--color-ring-secondary)",
    },
  },
  {
    type: "color",
    name: "color-ring-secondary-ghost",
    value: {
      light: "var(--color-ring-secondary)",
      dark: "var(--color-ring-secondary)",
    },
  },
]

export const SEMANTIC_COLORS_INFO = [
  // Text
  {
    type: "color",
    name: "color-text-info",
    value: {
      light: "var(--blue-700)",
      dark: "var(--blue-200)",
    },
  },
  // Soft
  {
    type: "color",
    name: "color-background-info-soft",
    value: {
      light: "var(--blue-50)",
      dark: "var(--blue-50)",
    },
  },
  {
    type: "color",
    name: "color-background-info-soft-hover",
    value: {
      light: "var(--blue-75)",
      dark: "var(--blue-75)",
    },
  },
  {
    type: "color",
    name: "color-background-info-soft-active",
    value: {
      light: "var(--blue-75)",
      dark: "var(--blue-75)",
    },
  },
  {
    type: "color",
    name: "color-background-info-soft-alpha",
    value: {
      light: "var(--blue-a50)",
      dark: "var(--blue-a50)",
    },
  },
  {
    type: "color",
    name: "color-background-info-soft-alpha-hover",
    value: {
      light: "var(--blue-a75)",
      dark: "var(--blue-a75)",
    },
  },
  {
    type: "color",
    name: "color-background-info-soft-alpha-active",
    value: {
      light: "var(--blue-a75)",
      dark: "var(--blue-a75)",
    },
  },
  {
    type: "color",
    name: "color-text-info-soft",
    value: {
      light: "var(--blue-600)",
      dark: "var(--blue-300)",
    },
  },

  // Surface
  {
    type: "color",
    name: "color-background-info-surface",
    value: {
      light: "var(--blue-a25)",
      dark: "var(--blue-a50)",
    },
  },
  {
    type: "color",
    name: "color-border-info-surface",
    value: {
      light: "var(--blue-a25)",
      dark: "var(--blue-a50)",
    },
  },
  {
    type: "color",
    name: "color-text-info-surface",
    value: {
      light: "var(--blue-600)",
      dark: "var(--blue-300)",
    },
  },

  // Solid
  {
    type: "color",
    name: "color-background-info-solid",
    value: {
      light: "var(--blue-400)",
      dark: "var(--blue-400)",
    },
  },
  {
    type: "color",
    name: "color-background-info-solid-hover",
    value: {
      light: "var(--blue-500)",
      dark: "var(--blue-500)",
    },
  },
  {
    type: "color",
    name: "color-background-info-solid-active",
    value: {
      light: "var(--blue-500)",
      dark: "var(--blue-500)",
    },
  },
  {
    type: "color",
    name: "color-text-info-solid",
    value: {
      light: "var(--white)",
      dark: "var(--white)",
    },
  },

  // Outline
  {
    type: "color",
    name: "color-background-info-outline-hover",
    value: {
      light: "var(--blue-a25)",
      dark: "var(--blue-a25)",
    },
  },
  {
    type: "color",
    name: "color-background-info-outline-active",
    value: {
      light: "var(--blue-a25)",
      dark: "var(--blue-a25)",
    },
  },
  {
    type: "color",
    name: "color-border-info-outline",
    value: {
      light: "var(--blue-500)",
      dark: "var(--blue-500)",
    },
  },
  {
    type: "color",
    name: "color-border-info-outline-hover",
    value: {
      light: "var(--blue-500)",
      dark: "var(--blue-500)",
    },
  },
  {
    type: "color",
    name: "color-text-info-outline",
    value: {
      light: "var(--blue-500)",
      dark: "var(--blue-500)",
    },
  },
  {
    type: "color",
    name: "color-text-info-outline-hover",
    value: {
      light: "var(--blue-500)",
      dark: "var(--blue-500)",
    },
  },

  // Ghost
  {
    type: "color",
    name: "color-background-info-ghost-hover",
    value: {
      light: "var(--blue-a50)",
      dark: "var(--blue-a50)",
    },
  },
  {
    type: "color",
    name: "color-background-info-ghost-active",
    value: {
      light: "var(--blue-a50)",
      dark: "var(--blue-a50)",
    },
  },
  {
    type: "color",
    name: "color-text-info-ghost",
    value: {
      light: "var(--blue-500)",
      dark: "var(--blue-200)",
    },
  },
  {
    type: "color",
    name: "color-text-info-ghost-hover",
    value: {
      light: "var(--blue-500)",
      dark: "var(--blue-200)",
    },
  },

  // Ring
  {
    type: "color",
    name: "color-ring-info",
    value: {
      light: "var(--color-ring)",
      dark: "var(--color-ring)",
    },
  },
  {
    type: "color",
    name: "color-ring-info-soft",
    value: {
      light: "var(--color-ring-info)",
      dark: "var(--color-ring-info)",
    },
  },
  {
    type: "color",
    name: "color-ring-info-solid",
    value: {
      light: "var(--color-ring-info)",
      dark: "var(--color-ring-info)",
    },
  },
  {
    type: "color",
    name: "color-ring-info-outline",
    value: {
      light: "var(--color-ring-info)",
      dark: "var(--color-ring-info)",
    },
  },
  {
    type: "color",
    name: "color-ring-info-ghost",
    value: {
      light: "var(--color-ring-info)",
      dark: "var(--color-ring-info)",
    },
  },
]

export const SEMANTIC_COLORS_WARNING = [
  // Text
  {
    type: "color",
    name: "color-text-warning",
    value: {
      light: "var(--orange-700)",
      dark: "var(--orange-500)",
    },
  },

  // Soft
  {
    type: "color",
    name: "color-background-warning-soft",
    value: {
      light: "var(--orange-50)",
      dark: "var(--orange-50)",
    },
  },
  {
    type: "color",
    name: "color-background-warning-soft-hover",
    value: {
      light: "var(--orange-75)",
      dark: "var(--orange-75)",
    },
  },
  {
    type: "color",
    name: "color-background-warning-soft-active",
    value: {
      light: "var(--orange-75)",
      dark: "var(--orange-75)",
    },
  },
  {
    type: "color",
    name: "color-background-warning-soft-alpha",
    value: {
      light: "var(--orange-a50)",
      dark: "var(--orange-a50)",
    },
  },
  {
    type: "color",
    name: "color-background-warning-soft-alpha-hover",
    value: {
      light: "var(--orange-a75)",
      dark: "var(--orange-a75)",
    },
  },
  {
    type: "color",
    name: "color-background-warning-soft-alpha-active",
    value: {
      light: "var(--orange-a75)",
      dark: "var(--orange-a75)",
    },
  },
  {
    type: "color",
    name: "color-text-warning-soft",
    value: {
      light: "var(--orange-700)",
      dark: "var(--orange-400)",
    },
  },

  // Surface
  {
    type: "color",
    name: "color-background-warning-surface",
    value: {
      light: "var(--orange-a25)",
      dark: "var(--orange-a50)",
    },
  },
  {
    type: "color",
    name: "color-border-warning-surface",
    value: {
      light: "var(--orange-a25)",
      dark: "var(--orange-a50)",
    },
  },
  {
    type: "color",
    name: "color-text-warning-surface",
    value: {
      light: "var(--orange-700)",
      dark: "var(--orange-400)",
    },
  },

  // Solid
  {
    type: "color",
    name: "color-background-warning-solid",
    value: {
      light: "var(--orange-500)",
      dark: "var(--orange-500)",
    },
  },
  {
    type: "color",
    name: "color-background-warning-solid-hover",
    value: {
      light: "var(--orange-600)",
      dark: "var(--orange-600)",
    },
  },
  {
    type: "color",
    name: "color-background-warning-solid-active",
    value: {
      light: "var(--orange-600)",
      dark: "var(--orange-600)",
    },
  },
  {
    type: "color",
    name: "color-text-warning-solid",
    value: {
      light: "var(--white)",
      dark: "var(--white)",
    },
  },

  // Outline
  {
    type: "color",
    name: "color-background-warning-outline-hover",
    value: {
      light: "var(--orange-a25)",
      dark: "var(--orange-a25)",
    },
  },
  {
    type: "color",
    name: "color-background-warning-outline-active",
    value: {
      light: "var(--orange-a25)",
      dark: "var(--orange-a25)",
    },
  },
  {
    type: "color",
    name: "color-border-warning-outline",
    value: {
      light: "var(--orange-500)",
      dark: "var(--orange-500)",
    },
  },
  {
    type: "color",
    name: "color-border-warning-outline-hover",
    value: {
      light: "var(--orange-500)",
      dark: "var(--orange-500)",
    },
  },
  {
    type: "color",
    name: "color-text-warning-outline",
    value: {
      light: "var(--orange-500)",
      dark: "var(--orange-500)",
    },
  },
  {
    type: "color",
    name: "color-text-warning-outline-hover",
    value: {
      light: "var(--orange-500)",
      dark: "var(--orange-500)",
    },
  },

  // Ghost
  {
    type: "color",
    name: "color-background-warning-ghost-hover",
    value: {
      light: "var(--orange-a50)",
      dark: "var(--orange-a50)",
    },
  },
  {
    type: "color",
    name: "color-background-warning-ghost-active",
    value: {
      light: "var(--orange-a50)",
      dark: "var(--orange-a50)",
    },
  },
  {
    type: "color",
    name: "color-text-warning-ghost",
    value: {
      light: "var(--orange-500)",
      dark: "var(--orange-500)",
    },
  },
  {
    type: "color",
    name: "color-text-warning-ghost-hover",
    value: {
      light: "var(--orange-500)",
      dark: "var(--orange-500)",
    },
  },

  // Ring
  {
    type: "color",
    name: "color-ring-warning",
    value: {
      light: "var(--color-ring)",
      dark: "var(--color-ring)",
    },
  },
  {
    type: "color",
    name: "color-ring-warning-soft",
    value: {
      light: "var(--color-ring-warning)",
      dark: "var(--color-ring-warning)",
    },
  },
  {
    type: "color",
    name: "color-ring-warning-solid",
    value: {
      light: "var(--color-ring-warning)",
      dark: "var(--color-ring-warning)",
    },
  },
  {
    type: "color",
    name: "color-ring-warning-outline",
    value: {
      light: "var(--color-ring-warning)",
      dark: "var(--color-ring-warning)",
    },
  },
  {
    type: "color",
    name: "color-ring-warning-ghost",
    value: {
      light: "var(--color-ring-warning)",
      dark: "var(--color-ring-warning)",
    },
  },
]

export const SEMANTIC_COLORS_CAUTION = [
  // Text
  {
    type: "color",
    name: "color-text-caution",
    value: {
      light: "var(--yellow-700)",
      dark: "var(--yellow-500)",
    },
  },

  // Soft
  {
    type: "color",
    name: "color-background-caution-soft",
    value: {
      light: "var(--yellow-50)",
      dark: "var(--yellow-50)",
    },
  },
  {
    type: "color",
    name: "color-background-caution-soft-hover",
    value: {
      light: "var(--yellow-75)",
      dark: "var(--yellow-75)",
    },
  },
  {
    type: "color",
    name: "color-background-caution-soft-active",
    value: {
      light: "var(--yellow-75)",
      dark: "var(--yellow-75)",
    },
  },
  {
    type: "color",
    name: "color-background-caution-soft-alpha",
    value: {
      light: "var(--yellow-a50)",
      dark: "var(--yellow-a50)",
    },
  },
  {
    type: "color",
    name: "color-background-caution-soft-alpha-hover",
    value: {
      light: "var(--yellow-a75)",
      dark: "var(--yellow-a75)",
    },
  },
  {
    type: "color",
    name: "color-background-caution-soft-alpha-active",
    value: {
      light: "var(--yellow-a75)",
      dark: "var(--yellow-a75)",
    },
  },
  {
    type: "color",
    name: "color-text-caution-soft",
    value: {
      light: "var(--yellow-800)",
      dark: "var(--yellow-400)",
    },
  },

  // Surface
  {
    type: "color",
    name: "color-background-caution-surface",
    value: {
      light: "var(--yellow-a25)",
      dark: "var(--yellow-a50)",
    },
  },
  {
    type: "color",
    name: "color-border-caution-surface",
    value: {
      light: "var(--yellow-a25)",
      dark: "var(--yellow-a50)",
    },
  },
  {
    type: "color",
    name: "color-text-caution-surface",
    value: {
      light: "var(--yellow-800)",
      dark: "var(--yellow-400)",
    },
  },

  // Solid
  {
    type: "color",
    name: "color-background-caution-solid",
    value: {
      light: "var(--yellow-600)",
      dark: "var(--yellow-600)",
    },
  },
  {
    type: "color",
    name: "color-background-caution-solid-hover",
    value: {
      light: "var(--yellow-700)",
      dark: "var(--yellow-700)",
    },
  },
  {
    type: "color",
    name: "color-background-caution-solid-active",
    value: {
      light: "var(--yellow-700)",
      dark: "var(--yellow-700)",
    },
  },

  // Outline
  {
    type: "color",
    name: "color-background-caution-outline-hover",
    value: {
      light: "var(--yellow-a25)",
      dark: "var(--yellow-a25)",
    },
  },
  {
    type: "color",
    name: "color-background-caution-outline-active",
    value: {
      light: "var(--yellow-a25)",
      dark: "var(--yellow-a25)",
    },
  },
  {
    type: "color",
    name: "color-border-caution-outline",
    value: {
      light: "var(--yellow-700)",
      dark: "var(--yellow-700)",
    },
  },
  {
    type: "color",
    name: "color-border-caution-outline-hover",
    value: {
      light: "var(--yellow-700)",
      dark: "var(--yellow-700)",
    },
  },
  {
    type: "color",
    name: "color-text-caution-outline",
    value: {
      light: "var(--yellow-700)",
      dark: "var(--yellow-700)",
    },
  },
  {
    type: "color",
    name: "color-text-caution-outline-hover",
    value: {
      light: "var(--yellow-700)",
      dark: "var(--yellow-700)",
    },
  },

  // Ghost
  {
    type: "color",
    name: "color-background-caution-ghost-hover",
    value: {
      light: "var(--yellow-a50)",
      dark: "var(--yellow-a50)",
    },
  },
  {
    type: "color",
    name: "color-background-caution-ghost-active",
    value: {
      light: "var(--yellow-a50)",
      dark: "var(--yellow-a50)",
    },
  },
  {
    type: "color",
    name: "color-text-caution-ghost",
    value: {
      light: "var(--yellow-700)",
      dark: "var(--yellow-700)",
    },
  },
  {
    type: "color",
    name: "color-text-caution-ghost-hover",
    value: {
      light: "var(--yellow-700)",
      dark: "var(--yellow-700)",
    },
  },

  // Ring
  {
    type: "color",
    name: "color-ring-caution",
    value: {
      light: "var(--color-ring)",
      dark: "var(--color-ring)",
    },
  },
  {
    type: "color",
    name: "color-ring-caution-soft",
    value: {
      light: "var(--color-ring-caution)",
      dark: "var(--color-ring-caution)",
    },
  },
  {
    type: "color",
    name: "color-ring-caution-solid",
    value: {
      light: "var(--color-ring-caution)",
      dark: "var(--color-ring-caution)",
    },
  },
  {
    type: "color",
    name: "color-ring-caution-outline",
    value: {
      light: "var(--color-ring-caution)",
      dark: "var(--color-ring-caution)",
    },
  },
  {
    type: "color",
    name: "color-ring-caution-ghost",
    value: {
      light: "var(--color-ring-caution)",
      dark: "var(--color-ring-caution)",
    },
  },
]

export const SEMANTIC_COLORS_DANGER = [
  // Text
  {
    type: "color",
    name: "color-text-danger",
    value: {
      light: "var(--red-700)",
      dark: "var(--red-500)",
    },
  },

  // Soft
  {
    type: "color",
    name: "color-background-danger-soft",
    value: {
      light: "var(--red-50)",
      dark: "var(--red-50)",
    },
  },
  {
    type: "color",
    name: "color-background-danger-soft-hover",
    value: {
      light: "var(--red-75)",
      dark: "var(--red-75)",
    },
  },
  {
    type: "color",
    name: "color-background-danger-soft-active",
    value: {
      light: "var(--red-75)",
      dark: "var(--red-75)",
    },
  },
  {
    type: "color",
    name: "color-background-danger-soft-alpha",
    value: {
      light: "var(--red-a50)",
      dark: "var(--red-a50)",
    },
  },
  {
    type: "color",
    name: "color-background-danger-soft-alpha-hover",
    value: {
      light: "var(--red-a75)",
      dark: "var(--red-a75)",
    },
  },
  {
    type: "color",
    name: "color-background-danger-soft-alpha-active",
    value: {
      light: "var(--red-a75)",
      dark: "var(--red-a75)",
    },
  },
  {
    type: "color",
    name: "color-text-danger-soft",
    value: {
      light: "var(--red-600)",
      dark: "var(--red-400)",
    },
  },

  // Surface
  {
    type: "color",
    name: "color-background-danger-surface",
    value: {
      light: "var(--red-a25)",
      dark: "var(--red-a50)",
    },
  },
  {
    type: "color",
    name: "color-border-danger-surface",
    value: {
      light: "var(--red-a25)",
      dark: "var(--red-a50)",
    },
  },
  {
    type: "color",
    name: "color-text-danger-surface",
    value: {
      light: "var(--red-600)",
      dark: "var(--red-400)",
    },
  },

  // Solid
  {
    type: "color",
    name: "color-background-danger-solid",
    value: {
      light: "var(--red-500)",
      dark: "var(--red-500)",
    },
  },
  {
    type: "color",
    name: "color-background-danger-solid-hover",
    value: {
      light: "var(--red-600)",
      dark: "var(--red-600)",
    },
  },
  {
    type: "color",
    name: "color-background-danger-solid-active",
    value: {
      light: "var(--red-600)",
      dark: "var(--red-600)",
    },
  },
  {
    type: "color",
    name: "color-text-danger-solid",
    value: {
      light: "var(--white)",
      dark: "var(--white)",
    },
  },

  // Outline
  {
    type: "color",
    name: "color-background-danger-outline-hover",
    value: {
      light: "var(--red-a25)",
      dark: "var(--red-a25)",
    },
  },
  {
    type: "color",
    name: "color-background-danger-outline-active",
    value: {
      light: "var(--red-a25)",
      dark: "var(--red-a25)",
    },
  },
  {
    type: "color",
    name: "color-border-danger-outline",
    value: {
      light: "var(--red-500)",
      dark: "var(--red-500)",
    },
  },
  {
    type: "color",
    name: "color-border-danger-outline-hover",
    value: {
      light: "var(--red-500)",
      dark: "var(--red-500)",
    },
  },
  {
    type: "color",
    name: "color-text-danger-outline",
    value: {
      light: "var(--red-500)",
      dark: "var(--red-500)",
    },
  },
  {
    type: "color",
    name: "color-text-danger-outline-hover",
    value: {
      light: "var(--red-500)",
      dark: "var(--red-500)",
    },
  },

  // Ghost
  {
    type: "color",
    name: "color-background-danger-ghost-hover",
    value: {
      light: "var(--red-a50)",
      dark: "var(--red-a50)",
    },
  },
  {
    type: "color",
    name: "color-background-danger-ghost-active",
    value: {
      light: "var(--red-a50)",
      dark: "var(--red-a50)",
    },
  },
  {
    type: "color",
    name: "color-text-danger-ghost",
    value: {
      light: "var(--red-500)",
      dark: "var(--red-500)",
    },
  },
  {
    type: "color",
    name: "color-text-danger-ghost-hover",
    value: {
      light: "var(--red-500)",
      dark: "var(--red-500)",
    },
  },

  // Ring
  {
    type: "color",
    name: "color-ring-danger",
    value: {
      light: "var(--red-200)",
      dark: "var(--red-200)",
    },
  },
  {
    type: "color",
    name: "color-ring-danger-soft",
    value: {
      light: "var(--color-ring-danger)",
      dark: "var(--color-ring-danger)",
    },
  },
  {
    type: "color",
    name: "color-ring-danger-solid",
    value: {
      light: "var(--color-ring-danger)",
      dark: "var(--color-ring-danger)",
    },
  },
  {
    type: "color",
    name: "color-ring-danger-outline",
    value: {
      light: "var(--color-ring-danger)",
      dark: "var(--color-ring-danger)",
    },
  },
  {
    type: "color",
    name: "color-ring-danger-ghost",
    value: {
      light: "var(--color-ring-danger)",
      dark: "var(--color-ring-danger)",
    },
  },
]

export const SEMANTIC_COLORS_SUCCESS = [
  // Text
  {
    type: "color",
    name: "color-text-success",
    value: {
      light: "var(--green-700)",
      dark: "var(--red-400)",
    },
  },

  // Soft
  {
    type: "color",
    name: "color-background-success-soft",
    value: {
      light: "var(--green-50)",
      dark: "var(--green-50)",
    },
  },
  {
    type: "color",
    name: "color-background-success-soft-hover",
    value: {
      light: "var(--green-75)",
      dark: "var(--green-75)",
    },
  },
  {
    type: "color",
    name: "color-background-success-soft-active",
    value: {
      light: "var(--green-75)",
      dark: "var(--green-75)",
    },
  },
  {
    type: "color",
    name: "color-background-success-soft-alpha",
    value: {
      light: "var(--green-a50)",
      dark: "var(--green-a50)",
    },
  },
  {
    type: "color",
    name: "color-background-success-soft-alpha-hover",
    value: {
      light: "var(--green-a75)",
      dark: "var(--green-a75)",
    },
  },
  {
    type: "color",
    name: "color-background-success-soft-alpha-active",
    value: {
      light: "var(--green-a75)",
      dark: "var(--green-a75)",
    },
  },
  {
    type: "color",
    name: "color-text-success-soft",
    value: {
      light: "var(--green-600)",
      dark: "var(--green-400)",
    },
  },

  // Surface
  {
    type: "color",
    name: "color-background-success-surface",
    value: {
      light: "var(--green-a25)",
      dark: "var(--green-a50)",
    },
  },
  {
    type: "color",
    name: "color-border-success-surface",
    value: {
      light: "var(--green-a25)",
      dark: "var(--green-a50)",
    },
  },
  {
    type: "color",
    name: "color-text-success-surface",
    value: {
      light: "var(--green-600)",
      dark: "var(--green-400)",
    },
  },

  // Solid
  {
    type: "color",
    name: "color-background-success-solid",
    value: {
      light: "var(--green-400)",
      dark: "var(--green-400)",
    },
  },
  {
    type: "color",
    name: "color-background-success-solid-hover",
    value: {
      light: "var(--green-500)",
      dark: "var(--green-500)",
    },
  },
  {
    type: "color",
    name: "color-background-success-solid-active",
    value: {
      light: "var(--green-500)",
      dark: "var(--green-500)",
    },
  },
  {
    type: "color",
    name: "color-text-success-solid",
    value: {
      light: "var(--white)",
      dark: "var(--white)",
    },
  },

  // Outline
  {
    type: "color",
    name: "color-background-success-outline-hover",
    value: {
      light: "var(--green-a25)",
      dark: "var(--green-a25)",
    },
  },
  {
    type: "color",
    name: "color-background-success-outline-active",
    value: {
      light: "var(--green-a25)",
      dark: "var(--green-a25)",
    },
  },
  {
    type: "color",
    name: "color-border-success-outline",
    value: {
      light: "var(--green-500)",
      dark: "var(--green-500)",
    },
  },
  {
    type: "color",
    name: "color-border-success-outline-hover",
    value: {
      light: "var(--green-500)",
      dark: "var(--green-500)",
    },
  },
  {
    type: "color",
    name: "color-text-success-outline",
    value: {
      light: "var(--green-500)",
      dark: "var(--green-500)",
    },
  },
  {
    type: "color",
    name: "color-text-success-outline-hover",
    value: {
      light: "var(--green-500)",
      dark: "var(--green-500)",
    },
  },

  // Ghost
  {
    type: "color",
    name: "color-background-success-ghost-hover",
    value: {
      light: "var(--green-a50)",
      dark: "var(--green-a50)",
    },
  },
  {
    type: "color",
    name: "color-background-success-ghost-active",
    value: {
      light: "var(--green-a50)",
      dark: "var(--green-a50)",
    },
  },
  {
    type: "color",
    name: "color-text-success-ghost",
    value: {
      light: "var(--green-500)",
      dark: "var(--green-500)",
    },
  },
  {
    type: "color",
    name: "color-text-success-ghost-hover",
    value: {
      light: "var(--green-500)",
      dark: "var(--green-500)",
    },
  },

  // Ring
  {
    type: "color",
    name: "color-ring-success",
    value: {
      light: "var(--color-ring)",
      dark: "var(--color-ring)",
    },
  },
  {
    type: "color",
    name: "color-ring-success-soft",
    value: {
      light: "var(--color-ring-info)",
      dark: "var(--color-ring-info)",
    },
  },
  {
    type: "color",
    name: "color-ring-success-solid",
    value: {
      light: "var(--color-ring-info)",
      dark: "var(--color-ring-info)",
    },
  },
  {
    type: "color",
    name: "color-ring-success-outline",
    value: {
      light: "var(--color-ring-info)",
      dark: "var(--color-ring-info)",
    },
  },
  {
    type: "color",
    name: "color-ring-success-ghost",
    value: {
      light: "var(--color-ring-info)",
      dark: "var(--color-ring-info)",
    },
  },
]

export const SEMANTIC_COLORS_DISCOVERY = [
  // Text
  {
    type: "color",
    name: "color-text-discovery",
    value: {
      light: "var(--purple-700)",
      dark: "var(--purple-500)",
    },
  },

  // Soft
  {
    type: "color",
    name: "color-background-discovery-soft",
    value: {
      light: "var(--purple-50)",
      dark: "var(--purple-50)",
    },
  },
  {
    type: "color",
    name: "color-background-discovery-soft-hover",
    value: {
      light: "var(--purple-75)",
      dark: "var(--purple-75)",
    },
  },
  {
    type: "color",
    name: "color-background-discovery-soft-active",
    value: {
      light: "var(--purple-75)",
      dark: "var(--purple-75)",
    },
  },
  {
    type: "color",
    name: "color-background-discovery-soft-alpha",
    value: {
      light: "var(--purple-a50)",
      dark: "var(--purple-a50)",
    },
  },
  {
    type: "color",
    name: "color-background-discovery-soft-alpha-hover",
    value: {
      light: "var(--purple-a75)",
      dark: "var(--purple-a75)",
    },
  },
  {
    type: "color",
    name: "color-background-discovery-soft-alpha-active",
    value: {
      light: "var(--purple-a75)",
      dark: "var(--purple-a75)",
    },
  },
  {
    type: "color",
    name: "color-text-discovery-soft",
    value: {
      light: "var(--purple-600)",
      dark: "var(--purple-300)",
    },
  },

  // Surface
  {
    type: "color",
    name: "color-background-discovery-surface",
    value: {
      light: "var(--purple-a25)",
      dark: "var(--purple-a50)",
    },
  },
  {
    type: "color",
    name: "color-border-discovery-surface",
    value: {
      light: "var(--purple-a25)",
      dark: "var(--purple-a50)",
    },
  },
  {
    type: "color",
    name: "color-text-discovery-surface",
    value: {
      light: "var(--purple-600)",
      dark: "var(--purple-200)",
    },
  },

  // Solid
  {
    type: "color",
    name: "color-background-discovery-solid",
    value: {
      light: "var(--purple-400)",
      dark: "var(--purple-400)",
    },
  },
  {
    type: "color",
    name: "color-background-discovery-solid-hover",
    value: {
      light: "var(--purple-500)",
      dark: "var(--purple-500)",
    },
  },
  {
    type: "color",
    name: "color-background-discovery-solid-active",
    value: {
      light: "var(--purple-500)",
      dark: "var(--purple-500)",
    },
  },
  {
    type: "color",
    name: "color-text-discovery-solid",
    value: {
      light: "var(--white)",
      dark: "var(--white)",
    },
  },

  // Outline
  {
    type: "color",
    name: "color-background-discovery-outline-hover",
    value: {
      light: "var(--purple-a25)",
      dark: "var(--purple-a25)",
    },
  },
  {
    type: "color",
    name: "color-background-discovery-outline-active",
    value: {
      light: "var(--purple-a25)",
      dark: "var(--purple-a25)",
    },
  },
  {
    type: "color",
    name: "color-border-discovery-outline",
    value: {
      light: "var(--purple-500)",
      dark: "var(--purple-500)",
    },
  },
  {
    type: "color",
    name: "color-border-discovery-outline-hover",
    value: {
      light: "var(--purple-500)",
      dark: "var(--purple-500)",
    },
  },
  {
    type: "color",
    name: "color-text-discovery-outline",
    value: {
      light: "var(--purple-500)",
      dark: "var(--purple-500)",
    },
  },
  {
    type: "color",
    name: "color-text-discovery-outline-hover",
    value: {
      light: "var(--purple-500)",
      dark: "var(--purple-500)",
    },
  },

  // Ghost
  {
    type: "color",
    name: "color-background-discovery-ghost-hover",
    value: {
      light: "var(--purple-a50)",
      dark: "var(--purple-a50)",
    },
  },
  {
    type: "color",
    name: "color-background-discovery-ghost-active",
    value: {
      light: "var(--purple-a50)",
      dark: "var(--purple-a50)",
    },
  },
  {
    type: "color",
    name: "color-text-discovery-ghost",
    value: {
      light: "var(--purple-500)",
      dark: "var(--purple-500)",
    },
  },
  {
    type: "color",
    name: "color-text-discovery-ghost-hover",
    value: {
      light: "var(--purple-500)",
      dark: "var(--purple-500)",
    },
  },

  // Ring
  {
    type: "color",
    name: "color-ring-discovery",
    value: {
      light: "var(--color-ring)",
      dark: "var(--color-ring)",
    },
  },
  {
    type: "color",
    name: "color-ring-discovery-soft",
    value: {
      light: "var(--color-ring)",
      dark: "var(--color-ring)",
    },
  },
  {
    type: "color",
    name: "color-ring-discovery-solid",
    value: {
      light: "var(--color-ring)",
      dark: "var(--color-ring)",
    },
  },
  {
    type: "color",
    name: "color-ring-discovery-outline",
    value: {
      light: "var(--color-ring)",
      dark: "var(--color-ring)",
    },
  },
  {
    type: "color",
    name: "color-ring-discovery-ghost",
    value: {
      light: "var(--color-ring)",
      dark: "var(--color-ring)",
    },
  },
]

export const SEMANTIC_COLORS_DISABLED = [
  {
    type: "color",
    name: "color-background-disabled",
    value: {
      light: "var(--alpha-05)",
      dark: "var(--alpha-05)",
    },
  },
  {
    type: "color",
    name: "color-border-disabled",
    value: {
      light: "var(--alpha-06)",
      dark: "var(--alpha-06)",
    },
  },
  {
    type: "color",
    name: "color-text-disabled",
    value: {
      light: "var(--gray-400)",
      dark: "var(--gray-500)",
    },
  },
]

const SEMANTIC_COLORS_MISC = [
  {
    type: "color",
    name: "color-ring",
    value: {
      light: "var(--blue-500)",
      dark: "var(--blue-400)",
    },
  },
  {
    type: "color",
    name: "color-border",
    value: {
      light: "var(--alpha-10)",
      dark: "var(--alpha-12)",
    },
  },
  {
    type: "color",
    name: "color-border-subtle",
    value: {
      light: "var(--alpha-05)",
      dark: "var(--alpha-06)",
    },
  },
  {
    type: "color",
    name: "color-border-strong",
    value: {
      light: "var(--alpha-15)",
      dark: "var(--alpha-20)",
    },
  },
  {
    type: "color",
    name: "color-surface",
    value: {
      light: "var(--gray-0)",
      dark: "var(--gray-200)",
    },
  },
  {
    type: "color",
    name: "color-surface-secondary",
    value: {
      light: "var(--gray-50)",
      dark: "var(--gray-100)",
    },
  },
  {
    type: "color",
    name: "color-surface-tertiary",
    value: {
      light: "var(--gray-75)",
      dark: "var(--gray-50)",
    },
  },
  {
    type: "color",
    name: "color-surface-elevated",
    value: {
      light: "var(--gray-0)",
      dark: "var(--gray-300)",
    },
  },
  {
    type: "color",
    name: "color-surface-elevated-secondary",
    value: {
      light: "var(--gray-50)",
      dark: "var(--gray-400)",
    },
  },
]

export const SEMANTIC_COLORS = [
  ...SEMANTIC_COLORS_PRIMARY,
  ...SEMANTIC_COLORS_SECONDARY,
  ...SEMANTIC_COLORS_INFO,
  ...SEMANTIC_COLORS_WARNING,
  ...SEMANTIC_COLORS_CAUTION,
  ...SEMANTIC_COLORS_DANGER,
  ...SEMANTIC_COLORS_SUCCESS,
  ...SEMANTIC_COLORS_DISCOVERY,
  ...SEMANTIC_COLORS_DISABLED,
  ...SEMANTIC_COLORS_MISC,
]

export const RADIUS = [
  {
    type: "radius",
    name: "radius-2xs",
    value: "0.125rem", // 2px
  },
  {
    type: "radius",
    name: "radius-xs",
    value: "0.25rem", // 4px
  },
  {
    type: "radius",
    name: "radius-sm",
    value: "0.375rem", // 6px
  },
  {
    type: "radius",
    name: "radius-md",
    value: "0.5rem", // 8px
  },
  {
    type: "radius",
    name: "radius-lg",
    value: "0.625rem", // 10px
  },
  {
    type: "radius",
    name: "radius-xl",
    value: "0.75rem", // 12px
  },
  {
    type: "radius",
    name: "radius-2xl",
    value: "1rem", // 16px
  },
  {
    type: "radius",
    name: "radius-3xl",
    value: "1.25rem", // 20px
  },
  {
    type: "radius",
    name: "radius-4xl",
    value: "1.5rem", // 24px
  },
  {
    type: "radius",
    name: "radius-full",
    value: "9999px",
  },
]

export const FONTS = [
  {
    type: "font-family",
    name: "font-sans",
    value: "ui-sans-serif, -apple-system, system-ui, ..., sans-serif",
  },
  {
    type: "font-family",
    name: "font-mono",
    value: 'ui-monospace, "SFMono-Regular", "SF Mono", ..., monospace',
  },
  {
    type: "font-weight",
    name: "font-weight-normal",
    value: "400",
  },
  {
    type: "font-weight",
    name: "font-weight-medium",
    value: "500",
  },
  {
    type: "font-weight",
    name: "font-weight-semibold",
    value: "600",
  },
  {
    type: "font-weight",
    name: "font-weight-bold",
    value: "700",
  },
  {
    type: "font-tracking",
    name: "font-tracking-wide",
    value: "0em",
  },
  {
    type: "font-tracking",
    name: "font-tracking-normal",
    value: "-0.01em",
  },
  {
    type: "font-tracking",
    name: "font-tracking-tight",
    value: "-0.02em",
  },
  // Headings
  { type: "font", name: "font-heading-5xl-size", value: "4.5rem" },
  { type: "font", name: "font-heading-5xl-line-height", value: "4.5rem" },
  { type: "font", name: "font-heading-5xl-weight", value: "var(--font-weight-semibold)" },
  { type: "font", name: "font-heading-5xl-tracking", value: "var(--tracking-tight)" },

  { type: "font", name: "font-heading-4xl-size", value: "3.75rem" },
  { type: "font", name: "font-heading-4xl-line-height", value: "3.75rem" },
  { type: "font", name: "font-heading-4xl-weight", value: "var(--font-weight-semibold)" },
  { type: "font", name: "font-heading-4xl-tracking", value: "var(--tracking-tight)" },

  { type: "font", name: "font-heading-3xl-size", value: "3rem" },
  { type: "font", name: "font-heading-3xl-line-height", value: "3rem" },
  { type: "font", name: "font-heading-3xl-weight", value: "var(--font-weight-semibold)" },
  { type: "font", name: "font-heading-3xl-tracking", value: "var(--tracking-tight)" },

  { type: "font", name: "font-heading-2xl-size", value: "2.25rem" },
  { type: "font", name: "font-heading-2xl-line-height", value: "2.625rem" },
  { type: "font", name: "font-heading-2xl-weight", value: "var(--font-weight-semibold)" },
  { type: "font", name: "font-heading-2xl-tracking", value: "var(--tracking-tight)" },

  { type: "font", name: "font-heading-xl-size", value: "2rem" },
  { type: "font", name: "font-heading-xl-line-height", value: "2.375rem" },
  { type: "font", name: "font-heading-xl-weight", value: "var(--font-weight-semibold)" },
  { type: "font", name: "font-heading-xl-tracking", value: "var(--tracking-tight)" },

  { type: "font", name: "font-heading-lg-size", value: "1.5rem" },
  { type: "font", name: "font-heading-lg-line-height", value: "1.75rem" },
  { type: "font", name: "font-heading-lg-weight", value: "var(--font-weight-semibold)" },
  { type: "font", name: "font-heading-lg-tracking", value: "var(--tracking-normal)" },

  { type: "font", name: "font-heading-md-size", value: "1.25rem" },
  { type: "font", name: "font-heading-md-line-height", value: "1.625rem" },
  { type: "font", name: "font-heading-md-weight", value: "var(--font-weight-semibold)" },
  { type: "font", name: "font-heading-md-tracking", value: "var(--tracking-normal)" },

  { type: "font", name: "font-heading-sm-size", value: "1.125rem" },
  { type: "font", name: "font-heading-sm-line-height", value: "1.625rem" },
  { type: "font", name: "font-heading-sm-weight", value: "var(--font-weight-semibold)" },
  { type: "font", name: "font-heading-sm-tracking", value: "var(--tracking-normal)" },

  { type: "font", name: "font-heading-xs-size", value: "1rem" },
  { type: "font", name: "font-heading-xs-line-height", value: "1.5rem" },
  { type: "font", name: "font-heading-xs-weight", value: "var(--font-weight-semibold)" },
  { type: "font", name: "font-heading-xs-tracking", value: "var(--tracking-normal)" },

  // Text
  { type: "font", name: "font-text-lg-size", value: "1.125rem" },
  { type: "font", name: "font-text-lg-line-height", value: "1.8125rem" },
  { type: "font", name: "font-text-lg-weight", value: "var(--font-weight-normal)" },
  { type: "font", name: "font-text-lg-tracking", value: "var(--tracking-normal)" },

  { type: "font", name: "font-text-md-size", value: "1rem" },
  { type: "font", name: "font-text-md-line-height", value: "1.5rem" },
  { type: "font", name: "font-text-md-weight", value: "var(--font-weight-normal)" },
  { type: "font", name: "font-text-md-tracking", value: "var(--tracking-normal)" },

  { type: "font", name: "font-text-sm-size", value: "0.875rem" },
  { type: "font", name: "font-text-sm-line-height", value: "1.25rem" },
  { type: "font", name: "font-text-sm-weight", value: "var(--font-weight-normal)" },
  { type: "font", name: "font-text-sm-tracking", value: "var(--tracking-normal)" },

  { type: "font", name: "font-text-xs-size", value: "0.75rem" },
  { type: "font", name: "font-text-xs-line-height", value: "1.125rem" },
  { type: "font", name: "font-text-xs-weight", value: "var(--font-weight-normal)" },
  { type: "font", name: "font-text-xs-tracking", value: "var(--tracking-wide)" },

  { type: "font", name: "font-text-2xs-size", value: "0.625rem" },
  { type: "font", name: "font-text-2xs-line-height", value: "0.875rem" },
  { type: "font", name: "font-text-2xs-weight", value: "var(--font-weight-normal)" },
  { type: "font", name: "font-text-2xs-tracking", value: "var(--tracking-wide)" },

  { type: "font", name: "font-text-3xs-size", value: "0.5rem" },
  { type: "font", name: "font-text-3xs-line-height", value: "0.75rem" },
  { type: "font", name: "font-text-3xs-weight", value: "var(--font-weight-normal)" },
  { type: "font", name: "font-text-3xs-tracking", value: "var(--tracking-wide)" },
]

export const SHADOWS = [
  {
    type: "shadow",
    name: "shadow-hairline",
  },

  // 100
  {
    type: "shadow",
    name: "shadow-100",
  },
  {
    type: "shadow",
    name: "shadow-100-strong",
  },
  {
    type: "shadow",
    name: "shadow-100-stronger",
  },

  // 200
  {
    type: "shadow",
    name: "shadow-200",
  },
  {
    type: "shadow",
    name: "shadow-200-strong",
  },
  {
    type: "shadow",
    name: "shadow-200-stronger",
  },

  // 300
  {
    type: "shadow",
    name: "shadow-300",
  },
  {
    type: "shadow",
    name: "shadow-300-strong",
  },
  {
    type: "shadow",
    name: "shadow-300-stronger",
  },

  // 400
  {
    type: "shadow",
    name: "shadow-400",
  },
  {
    type: "shadow",
    name: "shadow-400-strong",
  },
  {
    type: "shadow",
    name: "shadow-400-stronger",
  },
]

export const BREAKPOINTS = [
  {
    type: "value",
    name: "breakpoint-xs",
    value: "380px",
  },
  {
    type: "value",
    name: "breakpoint-sm",
    value: "576px",
  },
  {
    type: "value",
    name: "breakpoint-md",
    value: "768px",
  },
  {
    type: "value",
    name: "breakpoint-lg",
    value: "1024px",
  },
  {
    type: "value",
    name: "breakpoint-xl",
    value: "1280px",
  },
  {
    type: "value",
    name: "breakpoint-2xl",
    value: "1536px",
  },
]

export const MOTION = [
  // Cubic Beziers
  { type: "value", name: "cubic-enter", value: "cubic-bezier(0.19, 1, 0.22, 1)" },
  { type: "value", name: "cubic-exit", value: "cubic-bezier(0.8, 0, 0.4, 1)" },
  { type: "value", name: "cubic-exit-snappy", value: "cubic-bezier(0.65, 0, 0.4, 1)" },
  { type: "value", name: "cubic-move", value: "cubic-bezier(0.65, 0, 0.35, 1)" },

  // Transitions
  { type: "value", name: "transition-duration-basic", value: "150ms" },
  { type: "value", name: "transition-ease-basic", value: "ease" },
]


--- config/stylelint/stylelint-no-mixins-in-css.js ---
const stylelint = require("stylelint")

const ruleName = "oai/no-mixins-in-css"
const messages = stylelint.utils.ruleMessages(ruleName, {
  rejected:
    "Do not use `@mixin` in `.css` files. Use `@variant` instead. Mixins are only allowed in `.module.css` files.",
})

/** @type {import('stylelint').Rule} */
const rule = (_primaryOption, _secondaryOptions, _context) => {
  return (root, result) => {
    const validOptions = stylelint.utils.validateOptions(result, ruleName, {
      actual: _primaryOption,
    })
    if (!validOptions) return

    const filePath = root && root.source && root.source.input && root.source.input.file
    if (typeof filePath !== "string") return

    const isModuleCss = /\.module\.css$/i.test(filePath)
    const isCss = /\.css$/i.test(filePath)

    // Only enforce for `.css` that are not CSS Modules
    if (!(isCss && !isModuleCss)) return

    root.walkAtRules("mixin", (atRule) => {
      stylelint.utils.report({
        ruleName,
        result,
        message: messages.rejected,
        node: atRule,
      })
    })
  }
}

rule.ruleName = ruleName
rule.messages = messages

/** @type {import('stylelint').Plugin} */
const plugin = stylelint.createPlugin(ruleName, rule)

module.exports = plugin


--- config/stylelint/stylelint-no-top-level-breakpoint-mixin.js ---
const stylelint = require("stylelint")

const ruleName = "oai/no-top-level-breakpoint-mixin"
const messages = stylelint.utils.ruleMessages(ruleName, {
  rejected:
    "Do not use `@mixin breakpoint` at the top level; nest inside a selector. If you need to use a global breakpoint, use the global suffix (e.g. `@mixin breakpoint {size} global`).",
})

/** @type {import('stylelint').Rule} */
const rule = (_primaryOption, _secondaryOptions, _context) => {
  return (root, result) => {
    // Validate primary option for type-safety, even though the rule does not use it
    const validOptions = stylelint.utils.validateOptions(result, ruleName, {
      actual: _primaryOption,
    })
    if (!validOptions) return

    root.walkAtRules("mixin", (atRule) => {
      // Matches: @mixin breakpoint md { ... }
      const params = atRule.params || ""
      const isBreakpoint = /^\s*breakpoint\b/.test(params)
      const includesGlobal = /\bglobal\b/i.test(params)
      // Consider mixins inside wrappers like @layer/@media/@supports as top-level too
      // unless we encounter a selector rule before reaching the root.
      let parent = atRule.parent
      let isNestedInsideSelectorRule = false
      while (parent) {
        if (parent.type === "rule") {
          isNestedInsideSelectorRule = true
          break
        }
        if (parent.type === "root") {
          break
        }
        parent = parent.parent
      }

      if (isBreakpoint && !includesGlobal && !isNestedInsideSelectorRule) {
        stylelint.utils.report({
          ruleName,
          result,
          message: messages.rejected,
          node: atRule,
        })
      }
    })
  }
}

// Attach rule metadata as required by Stylelint typings
rule.ruleName = ruleName
rule.messages = messages

/** @type {import('stylelint').Plugin} */
const plugin = stylelint.createPlugin(ruleName, rule)

module.exports = plugin


--- src/Colors.mdx ---
import { Subtitle, Title, Meta } from "@storybook/blocks";
import { Colors } from "@storybookComponents/Colors";
import { HideTableOfContents } from "@storybookComponents/HideTableOfContents"

<HideTableOfContents />

<Meta title="Foundations/Colors" />

<Title>Colors</Title>
<Subtitle>Primitive color palettes available in Apps SDK UI</Subtitle>

<Colors />

--- src/global.d.ts ---
declare global {
  interface DefaultConfig {
    LinkComponent: "a"
    Breakpoint: "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
  }

  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
  interface AppsSDKUIOverrides {}

  // Utility type to merge defaults with overrides. The override keys take precedence.
  type MergeOverrides<Defaults, Overrides> = Omit<Defaults, keyof Overrides> & Overrides

  type Config = MergeOverrides<DefaultConfig, AppsSDKUIOverrides>

  namespace AppsSDKUI {
    export type LinkComponent = Config["LinkComponent"]
    export type Breakpoint = Config["Breakpoint"]
  }
}

export {}


--- src/Icons.mdx ---
import { Subtitle, Title, Meta } from "@storybook/blocks"
import { CustomIconGallery } from "@storybookComponents/CustomIconGallery"
import { HideTableOfContents } from "@storybookComponents/HideTableOfContents"

<HideTableOfContents />

<Meta title="Foundations/Icons" />

<Title>Icons</Title>
<Subtitle>Comprehensive list of all available icons</Subtitle>

### Usage

```jsx
import { IconName } from "@openai/apps-sdk-ui/components/Icon"
```

### List

<CustomIconGallery />


--- src/Introduction.mdx ---
import { linkTo } from "@storybook/addon-links"
import { Subtitle, Title, Meta, Unstyled } from "@storybook/blocks"
import { Card } from "@storybookComponents/Card"
import { HideTableOfContents } from "@storybookComponents/HideTableOfContents"
import { Terminal, Cube, Documentation, GridAlt } from "./components/Icon"

<HideTableOfContents />

<Meta title="Overview/Introduction" />

<Title>Apps SDK UI</Title>
<Subtitle>Design system for building high quality apps in ChatGPT</Subtitle>

Apps SDK UI is a design system tailored for ChatGPT [Apps SDK](https://developers.openai.com/apps-sdk), providing styling foundations with Tailwind, CSS variable design tokens, and a library of well-crafted, accessible components. Apps SDK UI includes:

- **Design tokens** &ndash; for colors, typography, spacing, sizing, shadows, surfaces, and more.
- **Tailwind 4** &ndash; pre-configured with Apps SDK UI's design tokens.
- **Component library** &ndash; high-quality components built on top of Radix for consistent accessibility patterns.
- **Utilities** &ndash; for dark mode, responsiveness layouts, and more.

## Get started

<Unstyled>
  <div className="flex gap-6">
    <Card
      icon={<Terminal />}
      title="Installation"
      subtitle="Start using Apps SDK UI in your app"
      onClick={linkTo("overview-installation")}
    />
    <Card
      icon={<Documentation />}
      title="Concepts"
      subtitle="Read about core concepts in Apps SDK UI"
      onClick={linkTo("concepts-dark-mode", "docs")}
    />
  </div>
  <div className="mt-6 flex gap-6">
    <Card
      icon={<Cube />}
      title="Components"
      subtitle="Explore our library of composable components"
      onClick={linkTo("components-avatar")}
    />
    <Card
      icon={<GridAlt />}
      title="Design tokens"
      subtitle="See all available design tokens"
      onClick={linkTo("foundations-design-tokens", "docs")}
    />
  </div>
</Unstyled>


## Links discovered
- [Apps SDK](https://developers.openai.com/apps-sdk)

--- src/types.ts ---
// reference is needed instead of import so consumer projects can compile properly
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference path="./global.d.ts" />

export type Size =
  | "5xs"
  | "4xs"
  | "3xs"
  | "2xs"
  | "xs"
  | "sm"
  | "md"
  | "lg"
  | "xl"
  | "2xl"
  | "3xl"
  | "4xl"
  | "5xl"
  | "6xl"
export type Sizes<T extends Size = Size> = T

export type ControlSize = Sizes<"3xs" | "2xs" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl">

export type Radius = "2xs" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "full"
export type Radii<T extends Radius = Radius> = T

export type TextColor = "base" | "emphasis" | "secondary" | "tertiary"
export type TextColors<T extends TextColor = TextColor> = T

export type SemanticColor =
  | "primary"
  | "secondary"
  | "danger"
  | "success"
  | "warning"
  | "caution"
  | "discovery"
  | "info"
export type SemanticColors<T extends SemanticColor = SemanticColor> = T

export type Variant = "solid" | "soft" | "outline" | "ghost"
export type Variants<T extends Variant = Variant> = T

export type Alignment = "start" | "center" | "end"
export type Alignments<T extends Alignment = Alignment> = T

export type FontWeight = "inherit" | "normal" | "medium" | "semibold" | "bold"
export type FontWeights<T extends FontWeight = FontWeight> = T


--- src/Typography.mdx ---
import { Subtitle, Title, Meta, Canvas, Unstyled } from "@storybook/blocks"
import { CustomTable, Value } from "@storybookComponents/CustomTable"
import { ArrowRight } from "./components/Icon"
import { TextLink } from "./components/TextLink"
import { NextPrev } from "@storybookComponents/NextPrev"
import { linkTo } from "@storybook/addon-links"
import * as TypographyStories from "./Typography.stories"

<Meta title="Concepts/Typography" />

<Title>Typography</Title>
<Subtitle>Using type treatments in Apps SDK UI</Subtitle>

## Scales

Scales include sizing for heading and text sizes, with combinations of `font-size`,`font-weight`, and `line-height`.

<CustomTable>
  <thead>
    <tr>
      <th scope="col">Name</th>
      <th scope="col" width="80">Size</th>
      <th scope="col" width="60">Weight</th>
      <th scope="col" width="80">Tracking</th>
      <th scope="col" width="60">Line</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td><span class="heading-5xl">heading-5xl</span></td>
      <td><Value>72px</Value></td>
      <td><Value>600</Value></td>
      <td><Value>0em</Value></td>
      <td><Value>72px</Value></td>
    </tr>
    <tr>
      <td><span class="heading-4xl">heading-4xl</span></td>
      <td><Value>60px</Value></td>
      <td><Value>600</Value></td>
      <td><Value>0em</Value></td>
      <td><Value>60px</Value></td>
    </tr>
    <tr>
      <td><span class="heading-3xl">heading-3xl</span></td>
      <td><Value>48px</Value></td>
      <td><Value>600</Value></td>
      <td><Value>0em</Value></td>
      <td><Value>48px</Value></td>
    </tr>
    <tr>
      <td><span class="heading-2xl">heading-2xl</span></td>
      <td><Value>36px</Value></td>
      <td><Value>600</Value></td>
      <td><Value>0em</Value></td>
      <td><Value>42px</Value></td>
    </tr>
    <tr>
      <td><span class="heading-xl">heading-xl</span></td>
      <td><Value>32px</Value></td>
      <td><Value>600</Value></td>
      <td><Value>0em</Value></td>
      <td><Value>38px</Value></td>
    </tr>
    <tr>
      <td><span class="heading-lg">heading-lg</span></td>
      <td><Value>24px</Value></td>
      <td><Value>600</Value></td>
      <td><Value>0em</Value></td>
      <td><Value>28px</Value></td>
    </tr>
    <tr>
      <td><span class="heading-md">heading-md</span></td>
      <td><Value>20px</Value></td>
      <td><Value>600</Value></td>
      <td><Value>0em</Value></td>
      <td><Value>26px</Value></td>
    </tr>
    <tr>
      <td><span class="heading-sm">heading-sm</span></td>
      <td><Value>18px</Value></td>
      <td><Value>600</Value></td>
      <td><Value>0em</Value></td>
      <td><Value>26px</Value></td>
    </tr>
    <tr>
      <td><span class="heading-xs">heading-xs</span></td>
      <td><Value>16px</Value></td>
      <td><Value>600</Value></td>
      <td><Value>0em</Value></td>
      <td><Value>24px</Value></td>
    </tr>
        <tr>
      <td><span class="text-lg">text-lg</span></td>
      <td><Value>18px</Value></td>
      <td><Value>400</Value></td>
      <td><Value>0em</Value></td>
      <td><Value>29px</Value></td>
    </tr>
    <tr>
      <td><span class="text-md">text-md</span></td>
      <td><Value>16px</Value></td>
      <td><Value>400</Value></td>
      <td><Value>0em</Value></td>
      <td><Value>24px</Value></td>
    </tr>
    <tr>
      <td><span class="text-sm">text-sm</span></td>
      <td><Value>14px</Value></td>
      <td><Value>400</Value></td>
      <td><Value>0em</Value></td>
      <td><Value>20px</Value></td>
    </tr>
    <tr>
      <td><span class="text-xs">text-xs</span></td>
      <td><Value>12px</Value></td>
      <td><Value>400</Value></td>
      <td><Value>0em</Value></td>
      <td><Value>18px</Value></td>
    </tr>
    <tr>
      <td><span class="text-2xs">text-2xs</span></td>
      <td><Value>10px</Value></td>
      <td><Value>400</Value></td>
      <td><Value>0em</Value></td>
      <td><Value>14px</Value></td>
    </tr>
    <tr>
      <td><span class="text-3xs">text-3xs</span></td>
      <td><Value>8px</Value></td>
      <td><Value>400</Value></td>
      <td><Value>0em</Value></td>
      <td><Value>12px</Value></td>
    </tr>
  </tbody>
</CustomTable>

All text sizes are exposed to Tailwind, with custom utilities for `heading-*` and `text-*` classes.

<Canvas
  of={TypographyStories.Sizes}
  source={{
    code: `
<h5 className="text-secondary mb-1">Get started</h5>
<h2 className="heading-xl mb-3">Building your first app</h2>
<p className="text-md">
  Inline cards in Apps SDK UI keep copy short and actionable. Provide just enough
  context for the task, then pair it with a clear next step.
</p>
`,
  }}
/>

The underlying CSS variables can be referenced directly in CSS, as needed.

```css
/* Headings */
--font-heading-xl-size: 2rem; /* 32px  */
--font-heading-xl-line-height: 2.375rem; /* 38px */
--font-heading-xl-weight: var(--font-weight-semibold);
/* Text */
--font-text-md-size: 1rem; /* 16px  */
--font-text-md-line-height: 1.5; /* 24px  */
--font-text-md-weight: var(--font-weight-normal);
```

## Colors

Four semantic text colors are provided by default &ndash; base, emphasis, prose, secondary, and tertiary.

<Canvas
  of={TypographyStories.Colors}
  source={{
    code: `
<p className="text-default">text-default</p>
<p className="text-secondary">text-secondary</p>
<p className="text-tertiary">text-tertiary</p>
`,
  }}
/>

<Unstyled>
  For more details on using semantic color variables directly,{" "}
  <TextLink onClick={linkTo("foundations-design-tokens", "docs")}>
    explore our design tokens
  </TextLink>
  .
</Unstyled>

## Weights

The available weights are fairly standard. Semibold is the most common bolded value.

<Canvas
  of={TypographyStories.Weights}
  source={{
    code: `
<p className="font-normal">font-normal</p>
<p className="font-medium">font-medium</p>
<p className="font-semibold">font-semibold</p>
<p className="font-bold">font-bold</p>
`,
  }}
/>

CSS variables are exposed in the common Tailwind pattern of `font-weight-*`:

```css
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
```

## Line height

Line heights are optimized for readability and tailored to how each `font-size` sits on the baseline.

Values are designed to create optimal centering with `align-items: center` for that given `font-size`, which ultimately means aligning to an odd or even pixel value.

<Canvas of={TypographyStories.LineHeight} sourceState="hidden" />


<NextPrev
  prev={{ title: "Responsive design", path: "concepts-responsive-design" }}
  next={{ title: "Colors", path: "foundations-colors" }}
/>


--- src/vite-env.d.ts ---
/// <reference types="vite/client" />


--- src/lib/assert.ts ---
export function assertIs<T>(a: unknown, b: T): asserts a is T {
  if (a !== b) {
    throw new Error(`Expected ${a} to be ${b}`)
  }
}


--- src/lib/casing.ts ---
export function filenameToTitleCase(filename: string): string {
  const nameWithoutExtension = filename.replace(/\.[^/.]+$/, "")
  const sanitized = nameWithoutExtension.replace(/[^a-zA-Z0-9]+/g, " ")

  return sanitized.trim().split(/\s+/).map(capitalize).join(" ")
}

export function kebabCaseToPascalCase(name: string): string {
  const sanitized = name.replace(/[^a-zA-Z0-9]+/g, " ")

  return sanitized.trim().split(/\s+/).map(capitalize).join("")
}

export function capitalize<T extends string>(str: T): Capitalize<string> {
  if (!str) {
    return ""
  }
  return (str.charAt(0).toUpperCase() + str.slice(1)) as Capitalize<string>
}


--- test/executeWithRetries.test.ts ---
import { describe, expect, test } from "vitest"
import { executeWithRetries } from "./utils/executeWithRetries"

describe("executeWithRetries", () => {
  test("succeeds on first attempt and calls fn once", async () => {
    let calls = 0
    const result = await executeWithRetries(5, () => {
      calls += 1
      return 42
    })
    expect(result).toBe(42)
    expect(calls).toBe(1)
  })

  test("succeeds on Nth attempt (async)", async () => {
    let calls = 0
    const result = await executeWithRetries(5, async () => {
      calls += 1
      if (calls < 3) throw new Error("fail")
      return "ok"
    })
    expect(result).toBe("ok")
    expect(calls).toBe(3)
  })

  test("throws after max retries and calls fn max times", async () => {
    let calls = 0
    let failures = 0
    await expect(
      executeWithRetries(
        3,
        () => {
          calls += 1
          throw new Error("always fail")
        },
        () => {
          failures += 1
        },
      ),
    ).rejects.toThrow("always fail")
    expect(calls).toBe(3)
    expect(failures).toBe(3)
  })
})


--- test/retry-globals.d.ts ---
declare global {
  function retryTest(maxRetries: number, name: string, fn: () => Promise<void> | void): void
}

export {}


--- test/setupTests.ts ---
import { cleanup } from "@testing-library/react"
import { test } from "vitest"
import { executeWithRetries } from "./utils/executeWithRetries"

function globalRetryTest(maxRetries: number, name: string, fn: () => Promise<void> | void) {
  test(name, async () => {
    await executeWithRetries(
      maxRetries,
      async () => {
        await fn()
      },
      async () => {
        // Ensure DOM is cleared between attempts
        cleanup()
      },
    )
  })
}

type GlobalThis = typeof globalThis
type GlobalThisWithRetryTest = GlobalThis & {
  retryTest: typeof globalRetryTest
}

const g = globalThis as GlobalThisWithRetryTest
g.retryTest = globalRetryTest


--- test/utils/executeWithRetries.ts ---
export async function executeWithRetries<T>(
  maxRetries: number,
  fn: () => Promise<T> | T,
  onAttemptFailure?: (attempt: number, error: unknown) => Promise<void> | void,
): Promise<T> {
  let lastError: unknown
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await fn()
    } catch (err) {
      lastError = err
      if (onAttemptFailure) await onAttemptFailure(attempt, err)
      if (attempt === maxRetries) {
        throw lastError
      }
    }
  }
  // Should be unreachable, but type-safe fallback
  throw lastError
}
