Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion samples/client/lit/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 25 additions & 28 deletions samples/client/lit/shell/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,44 @@ This is a UI to generate and visualize A2UI responses.

## Prerequisites

1. [nodejs](https://nodejs.org/en)
* [nodejs](https://nodejs.org/en)
* [uv](https://docs.astral.sh/uv/getting-started/installation/)

## Running

This sample depends on the Lit renderer. Before running this sample, you need to build the renderer.
### Configure Gemini API Key

1. **Build the renderer:**
```bash
cd ../../../renderers/web_core
npm install
npm run build
cd ../lit
npm install
npm run build
```
This step is **required** for the backend to work.

2. **Run this sample:**
```bash
cd - # back to the sample directory
npm install
```
- Navigate to the respective agent directory (e.g., `samples/agent/adk/restaurant_finder`
or `samples/agent/adk/contact_lookup`).
- Copy `.env.example` to `.env` and set your `GEMINI_API_KEY`.

3. **Run the servers:**
- Run the [Restaurant Finder Agent](../../../agent/adk/restaurant_finder/) (Default): `npm run demo:restaurant`
- Run the dev server: `npm run dev`
(More details can be found in the READMEs of the [agent samples](/samples/agent/adk).)

### Running the Contact Sample
### Run the Demo and Servers

The shell app supports multiple configured applications. To run the Contact sample:
From the `samples/client/lit` directory:

1. **Start the Contact Agent:**
```bash
npm run demo:contact
```
- Run the **Restaurant Finder** demo (starts both the agent and the shell):
```bash
npm run demo:restaurant09
```
- Or run the **Contact Lookup** demo:
```bash
npm run demo:contact09
```

2. **Open the Contact App:**
- Open `http://localhost:5173/?app=contacts`
### Open the Application

From a web browser:

- Open `http://localhost:5173/` for the default application (Restaurant Finder).
- Open `http://localhost:5173/?app=contacts` for the Contact Lookup application.

> **Note:** The `?app=` query parameter only supports apps that are actively configured in `app.ts` (e.g., `restaurant`, `contacts`). You cannot run arbitrary agents by passing their URL as a query string without first adding them to the shell configuration.

After starting the dev server, you can open http://localhost:5173/ to view the sample.
## Security Notice

Important: The sample code provided is for demonstration purposes and illustrates the mechanics of A2UI and the Agent-to-Agent (A2A) protocol. When building production applications, it is critical to treat any agent operating outside of your direct control as a potentially untrusted entity.

Expand Down
172 changes: 19 additions & 153 deletions samples/client/lit/shell/THEMING.md
Original file line number Diff line number Diff line change
@@ -1,163 +1,29 @@
# A2UI Theming & Configuration Guide
# A2UI Lit v0.9 Theming & Configuration Guide

This guide explains how the Universal App Shell handles theming and how to add new sample applications seamlessly.
This document describes the styling and configuration architecture for the v0.9 A2UI Lit Shell.

## Architecture Overview
## Architecture

The styling system is built on two distinct layers:
### Design Tokens and CSS Variables

### 1. **Base Layer (`default-theme.ts`)**
This application uses A2UI's "Basic Catalog", which has some theming features.

- **Role**: Structural & Functional Styles.
- **What it does**: Maps A2UI components (like `Text`, `Card`, `Row`) to functional CSS utility classes (e.g., `layout-w-100`, `typography-f-sf`).
- **When to touch**: Rarely. Only if you need to change the fundamental layout behavior of a component across all shell apps.
Themes can be configured by overriding default CSS variables provided by the
Lit renderer basic catalog implementation.

### 2. **Configuration Layer (`configs/*.ts`)**
Design tokens are defined in two layers:

- **Role**: App Identity & Brand Overrides.
- **What it does**: Allows for app-level theme overrides.
- **Key Mechanism**: The `AppConfig` interface allows you to provide a new theme by setting items in the `theme` property.
- **When to touch**: Whenever you add a new app and want to change an app's theme from the default theme provided with the shell.
- **Web Core**: Supplies base design tokens (color palettes, typography, spacing)
that are used by the A2UI-provided renderers via global CSS custom properties on the root element. See the [Basic Catalog default styles](renderers/web_core/src/v0_9/basic_catalog/styles/default.ts).
- **Lit Renderer**: Each Basic Catalog component provided by the Lit renderer
has additional design tokens to target more-specific properties (e.g., `--a2ui-button-background`). View available components and the tokens they
expose in the [Lit Basic Catalog Components](renderers/lit/src/v0_9/catalogs/basic/components).

---
### Application Configuration

## How to Add a New Sample App
In this particular app:

Follow these steps to add a new application (e.g., "Flight Booker") with its own unique theme.

### Step 1: Create the Config

Create a new file `configs/flights.ts`:

```typescript
import { AppConfig } from "./types.js";
import { cloneDefaultTheme } from "../theme/clone-default-theme.js";

const theme = cloneDefaultTheme();
// Set your variables, e.g., theme.components.Card = { 'color-bgc-n100': true }

export const config: AppConfig = {
key: "flights",
title: "Flight Booker",
heroImage: "/hero-flights.png",
heroImageDark: "/hero-flights-dark.png", // Optional
placeholder: "Where do you want to go?",
loadingText: ["Checking availability...", "Finding best rates..."],
serverUrl: "http://localhost:10004", // Your agent's URL
theme, // Apply the theme.
};
```

### Step 2: Register the Config

Update `app.ts` to include your new config:

```typescript
import { config as flightsConfig } from "./configs/flights.js";

const configs: Record<string, AppConfig> = {
restaurant: restaurantConfig,
contacts: contactsConfig,
flights: flightsConfig, // Add this line
};
```

### Step 3: Run It

Access your new app by adding the `app` query parameter:
`http://localhost:5173/?app=flights`

The App Shell will automatically:

1. Load your `flights` config.
2. Apply your theme to the A2UI root's theme context.
3. Connect to your specified `serverUrl`.

---

## Reference: Styling Levers

This section lists the available styling "levers" (utility classes) you can use in your `theme.ts` file or directly in your components. These are defined in the core library (`renderers/lit/src/0.8/styles`).

### 1. Layout (`layout-`)

**Source:** `styles/layout.ts`

| Category | Prefix | Scale/Values | Examples |
| :-------------- | :------------ | :------------------------------------------ | :---------------------------------------------------------- |
| **Padding** | `layout-p-` | 0-24 (1 = 4px) | `layout-p-4` (16px), `layout-pt-2` (Top 8px), `layout-px-4` |
| **Margin** | `layout-m-` | 0-24 (1 = 4px) | `layout-m-0`, `layout-mb-4` (Bottom 16px), `layout-mx-auto` |
| **Gap** | `layout-g-` | 0-24 (1 = 4px) | `layout-g-2` (8px), `layout-g-4` (16px) |
| **Width** | `layout-w-` | 10-100 (Percentage) | `layout-w-100` (100%), `layout-w-50` (50%) |
| **Width (Px)** | `layout-wp-` | 0-15 (1 = 4px) | `layout-wp-10` (40px) |
| **Height** | `layout-h-` | 10-100 (Percentage) | `layout-h-100` (100%) |
| **Height (Px)** | `layout-hp-` | 0-15 (1 = 4px) | `layout-hp-10` (40px) |
| **Display** | `layout-dsp-` | `none`, `block`, `grid`, `flex`, `iflex` | `layout-dsp-flexhor` (Row), `layout-dsp-flexvert` (Col) |
| **Alignment** | `layout-al-` | `fs` (Start), `fe` (End), `c` (Center) | `layout-al-c` (Align Items Center) |
| **Justify** | `layout-sp-` | `c` (Center), `bt` (Between), `ev` (Evenly) | `layout-sp-bt` (Justify Content Space Between) |
| **Flex** | `layout-flx-` | `0` (None), `1` (Grow) | `layout-flx-1` (Flex Grow 1) |
| **Position** | `layout-pos-` | `a` (Absolute), `rel` (Relative) | `layout-pos-rel` |

### 2. Colors (`color-`)

**Source:** `styles/colors.ts`

| Category | Prefix | Scale/Values | Examples |
| :--------------- | :----------- | :------------------ | :-------------------------------------------------------------------- |
| **Text Color** | `color-c-` | Palette Key + Shade | `color-c-p50` (Primary), `color-c-n10` (Black), `color-c-e40` (Error) |
| **Background** | `color-bgc-` | Palette Key + Shade | `color-bgc-p100` (White/Lightest), `color-bgc-s30` (Secondary Dark) |
| **Border Color** | `color-bc-` | Palette Key + Shade | `color-bc-p60` (Primary Border) |

**Palette Keys:**

- `p` = Primary (Brand)
- `s` = Secondary
- `t` = Tertiary
- `n` = Neutral (Grays)
- `nv` = Neutral Variant
- `e` = Error

**Shades:** 0, 5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 70, 80, 90, 95, 98, 99, 100

### 3. Typography (`typography-`)

**Source:** `styles/type.ts`

| Category | Prefix | Scale/Values | Examples |
| :------------------ | :--------------- | :---------------------------------------- | :----------------------------------------------------------------------------------- |
| **Font Family** | `typography-f-` | `sf` (Sans/Flex), `s` (Serif), `c` (Code) | `typography-f-sf` (System UI / Outfit) |
| **Weight** | `typography-w-` | 100-900 | `typography-w-400` (Regular), `typography-w-500` (Medium), `typography-w-700` (Bold) |
| **Size (Body)** | `typography-sz-` | `bs`, `bm`, `bl` | `typography-sz-bm` (Body Medium - 14px) |
| **Size (Title)** | `typography-sz-` | `ts`, `tm`, `tl` | `typography-sz-tl` (Title Large - 22px) |
| **Size (Headline)** | `typography-sz-` | `hs`, `hm`, `hl` | `typography-sz-hl` (Headline Large - 32px) |
| **Size (Display)** | `typography-sz-` | `ds`, `dm`, `dl` | `typography-sz-dl` (Display Large - 57px) |
| **Align** | `typography-ta-` | `s` (Start), `c` (Center) | `typography-ta-c` |

### 4. Borders (`border-`)

**Source:** `styles/border.ts`

| Category | Prefix | Scale/Values | Examples |
| :--------- | :----------- | :------------- | :---------------------------------------------------- |
| **Radius** | `border-br-` | 0-24 (1 = 4px) | `border-br-4` (16px), `border-br-50pc` (50% / Circle) |
| **Width** | `border-bw-` | 0-24 (Pixels) | `border-bw-1` (1px), `border-bw-2` (2px) |
| **Style** | `border-bs-` | `s` (Solid) | `border-bs-s` |

### 5. Behavior & Opacity

**Source:** `styles/behavior.ts`, `styles/opacity.ts`

| Category | Prefix | Scale/Values | Examples |
| :---------------- | :------------- | :------------------------------------- | :-------------------------------------- |
| **Hover Opacity** | `behavior-ho-` | 0-100 (Step 5) | `behavior-ho-80` (Opacity 0.8 on hover) |
| **Opacity** | `opacity-el-` | 0-100 (Step 5) | `opacity-el-50` (Opacity 0.5) |
| **Overflow** | `behavior-o-` | `s` (Scroll), `a` (Auto), `h` (Hidden) | `behavior-o-h` |
| **Scrollbar** | `behavior-sw-` | `n` (None) | `behavior-sw-n` |

### 6. Icons

**Source:** `styles/icons.ts`

- Class: `.g-icon`
- Variants: `.filled`, `.filled-heavy`
- Usage: `<span class="g-icon">icon_name</span>`
- Application themes are defined using `CSSStyleSheet` instances. See:
- [Restaurants theme](theme/restaurant-theme.ts)
- These stylesheets override the default component CSS variables specified above,
and change the look and feel of the generated UI.
Loading
Loading