> ## Documentation Index
> Fetch the complete documentation index at: https://docs.whop.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Theming & styles

> Customize the appearance of chat elements

export const Platform = ({value, children}) => {
  const values = Array.isArray(value) ? value : [value];
  return <div className="pp-content" data-platforms={values.join(" ")}>
			{children}
		</div>;
};

export const PlatformSelect = ({children}) => {
  const platforms = [{
    value: "react",
    label: "React"
  }, {
    value: "vanillajs",
    label: "Vanilla JS"
  }, {
    value: "swift",
    label: "Swift"
  }];
  const authMethods = [{
    value: "token",
    label: "Token"
  }, {
    value: "oauth",
    label: "OAuth"
  }];
  const [selected, setSelected] = React.useState("react");
  const [selectedAuth, setSelectedAuth] = React.useState("token");
  const wrapperRef = React.useRef(null);
  React.useEffect(() => {
    const wrapper = wrapperRef.current;
    if (!wrapper) return;
    const updateToc = () => {
      const hiddenIds = new Set();
      const visibleIds = new Set();
      wrapper.querySelectorAll(".pp-content").forEach(el => {
        const plats = (el.getAttribute("data-platforms") || "").split(" ");
        const isVisible = plats.includes(selected);
        el.querySelectorAll("[id]").forEach(child => {
          if (isVisible) {
            visibleIds.add(child.id);
          } else {
            hiddenIds.add(child.id);
          }
        });
      });
      wrapper.querySelectorAll(".pp-content-auth").forEach(el => {
        const modes = (el.getAttribute("data-auth-modes") || "").split(" ");
        const isVisible = modes.includes(selectedAuth);
        el.querySelectorAll("[id]").forEach(child => {
          if (isVisible) {
            visibleIds.add(child.id);
          } else {
            hiddenIds.add(child.id);
          }
        });
      });
      document.querySelectorAll('a[href^="#"]').forEach(a => {
        const id = decodeURIComponent(a.getAttribute("href").slice(1));
        const li = a.closest("li");
        if (!li) return;
        if (hiddenIds.has(id) && !visibleIds.has(id)) {
          li.style.display = "none";
        } else if (visibleIds.has(id) || hiddenIds.has(id)) {
          li.style.display = "";
        }
      });
    };
    updateToc();
    const timer = setTimeout(updateToc, 200);
    return () => clearTimeout(timer);
  }, [selected, selectedAuth]);
  return <div className="pp-wrapper" ref={wrapperRef} data-selected-platform={selected} data-selected-auth={selectedAuth}>
			<div className="pp-bar">
				<div className="pp-group">
					<span className="pp-label">Auth</span>
					<div className="pp-buttons">
						{authMethods.map(p => <button key={p.value} onClick={() => setSelectedAuth(p.value)} className={`pp-button ${selectedAuth === p.value ? "pp-button-active" : ""}`} aria-pressed={selectedAuth === p.value}>
								{p.label}
							</button>)}
					</div>
					<select className="pp-select" value={selectedAuth} onChange={e => setSelectedAuth(e.target.value)}>
						{authMethods.map(p => <option key={p.value} value={p.value}>
								{p.label}
							</option>)}
					</select>
				</div>
				<div className="pp-group">
					<span className="pp-label">Platform</span>
					<div className="pp-buttons">
						{platforms.map(p => <button key={p.value} onClick={() => setSelected(p.value)} className={`pp-button ${selected === p.value ? "pp-button-active" : ""}`} aria-pressed={selected === p.value}>
								{p.label}
							</button>)}
					</div>
					<select className="pp-select" value={selected} onChange={e => setSelected(e.target.value)}>
						{platforms.map(p => <option key={p.value} value={p.value}>
								{p.label}
							</option>)}
					</select>
				</div>
			</div>
			{children}
		</div>;
};

<PlatformSelect>
  <Platform value="react">
    ## Theming

    Customize the appearance of chat elements by passing a `theme` inside the `appearance` option on the `Elements` provider.

    ```tsx theme={null}
    <Elements
    	elements={elements}
    	appearance={{
    		theme: {
    			appearance: "dark",
    			accentColor: "blue",
    			grayColor: "gray",
    			dangerColor: "red",
    			warningColor: "amber",
    			successColor: "green",
    			infoColor: "sky",
    		},
    	}}
    >
    	<ChatSession token={getToken}>
    		<ChatElement options={chatOptions} />
    	</ChatSession>
    </Elements>
    ```

    ### Theme properties

    | Property       | Default   | Description                                               |
    | -------------- | --------- | --------------------------------------------------------- |
    | `appearance`   | —         | Light or dark mode (`"light"`, `"dark"`)                  |
    | `accentColor`  | `"blue"`  | Primary interactive elements (buttons, links, highlights) |
    | `grayColor`    | `"gray"`  | Neutral color palette for text, borders, and backgrounds  |
    | `dangerColor`  | `"red"`   | Destructive actions and error states                      |
    | `warningColor` | `"amber"` | Warning states                                            |
    | `successColor` | `"green"` | Success states                                            |
    | `infoColor`    | `"sky"`   | Informational highlights                                  |

    ### Available colors

    All color properties accept any of the following tints:

    `amber` · `blue` · `bronze` · `brown` · `crimson` · `cyan` · `gold` · `grass` · `gray` · `green` · `indigo` · `iris` · `jade` · `lemon` · `lime` · `magenta` · `mint` · `orange` · `pink` · `plum` · `purple` · `red` · `ruby` · `sky` · `teal` · `tomato` · `violet` · `yellow`

    ## Chat styles

    Choose between Discord-style or iMessage-style chat. iMessage style (bubble chat) is the default if not provided:

    ```tsx theme={null}
    const chatOptions: ChatElementOptions = useMemo(() => {
    	return {
    		channelId: "chat_XXXXXXXXXXXXXX",
    		style: "discord", // or "imessage" (default)
    	};
    }, []);
    ```
  </Platform>

  <Platform value="vanillajs">
    ## Theming

    Customize the appearance of chat elements by passing a `theme` inside the `appearance` option.

    ```typescript theme={null}
    const whopElements = await loadWhopElements();

    whopElements.updateOptions({
    	appearance: {
    		theme: {
    			appearance: "dark",
    			accentColor: "blue",
    			grayColor: "gray",
    			dangerColor: "red",
    			warningColor: "amber",
    			successColor: "green",
    			infoColor: "sky",
    		},
    	},
    });
    ```

    ### Theme properties

    | Property       | Default   | Description                                               |
    | -------------- | --------- | --------------------------------------------------------- |
    | `appearance`   | —         | Light or dark mode (`"light"`, `"dark"`)                  |
    | `accentColor`  | `"blue"`  | Primary interactive elements (buttons, links, highlights) |
    | `grayColor`    | `"gray"`  | Neutral color palette for text, borders, and backgrounds  |
    | `dangerColor`  | `"red"`   | Destructive actions and error states                      |
    | `warningColor` | `"amber"` | Warning states                                            |
    | `successColor` | `"green"` | Success states                                            |
    | `infoColor`    | `"sky"`   | Informational highlights                                  |

    ### Available colors

    All color properties accept any of the following tints:

    `amber` · `blue` · `bronze` · `brown` · `crimson` · `cyan` · `gold` · `grass` · `gray` · `green` · `indigo` · `iris` · `jade` · `lemon` · `lime` · `magenta` · `mint` · `orange` · `pink` · `plum` · `purple` · `red` · `ruby` · `sky` · `teal` · `tomato` · `violet` · `yellow`

    ## Chat styles

    Choose between Discord-style or iMessage-style chat. iMessage style (bubble chat) is the default if not provided:

    ```typescript theme={null}
    const chatElement = session.createElement("chat-element", {
    	channelId: "chat_XXXXXXXXXXXXXX",
    	style: "discord", // or "imessage" (default)
    });
    ```
  </Platform>

  <Platform value="swift">
    ## Theming

    Customize the color palette of chat views and the DMs list using `WhopTheme` and the `.whopTheme()` modifier. The theme propagates through SwiftUI's environment to all child SDK views.

    ```swift theme={null}
    struct ThemedMessagesView: View {
        @State private var selectedChannel: DMChannel?

        let theme = WhopTheme(
            accent: .plum,
            neutral: .gray,
            danger: .tomato,
            warning: .violet
        )

        var body: some View {
            WhopDMsListView(
                onEvent: { event in
                    switch event {
                    case let .channelSelected(channel):
                        selectedChannel = channel
                    }
                }
            )
            .whopTheme(theme)
            .navigationDestination(item: $selectedChannel) { channel in
                WhopChatView(
                    channelId: channel.id,
                    style: .imessage
                )
                .whopTheme(theme)
                .navigationBarTitleDisplayMode(.inline)
                .navigationTitle(channel.name)
            }
        }
    }
    ```

    ### Theme properties

    `WhopTheme` defines six semantic color slots, each accepting a `WhopTint` value:

    | Property  | Default  | Description                                                         |
    | --------- | -------- | ------------------------------------------------------------------- |
    | `accent`  | `.blue`  | Primary interactive elements (buttons, links, selection highlights) |
    | `neutral` | `.gray`  | Text, borders, and backgrounds                                      |
    | `danger`  | `.red`   | Destructive actions and error states                                |
    | `info`    | `.sky`   | Informational highlights                                            |
    | `success` | `.green` | Success states                                                      |
    | `warning` | `.amber` | Warning states                                                      |

    ### Available tints

    All properties accept any of the following `WhopTint` values that adapt to light and dark mode:

    `amber` · `blue` · `bronze` · `brown` · `crimson` · `cyan` · `gold` · `grass` · `gray` · `green` · `indigo` · `iris` · `jade` · `lemon` · `lime` · `magenta` · `mint` · `orange` · `pink` · `plum` · `purple` · `red` · `ruby` · `sky` · `teal` · `tomato` · `violet` · `yellow`

    ## Chat styles

    Choose between Discord-style or iMessage-style chat. iMessage style (bubble chat) is the default if not provided:

    ```swift theme={null}
    // iMessage style (bubble chat)
    WhopChatView(
        channelId: "chat_XXXXXXXXXXXXXX",
        style: .imessage
    )

    // Discord style (full-width messages)
    WhopChatView(
        channelId: "chat_XXXXXXXXXXXXXX",
        style: .discord
    )
    ```
  </Platform>
</PlatformSelect>
