> ## 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.

# DMs list element

> Display a list of direct message conversations

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>
  The DMs list element renders a navigable list of the user's direct message conversations.

  ### Basic usage

  Mount the DMs list and listen for channel selection events to navigate users into a conversation.

  <Platform value="react">
    ```tsx theme={null}
    import { useCallback, useMemo, useState } from "react";
    import {
    	ChatSession,
    	DmsListElement,
    	Elements,
    } from "@whop/embedded-components-react-js";
    import { loadWhopElements } from "@whop/embedded-components-vanilla-js";
    import type {
    	DmsListElementEvent,
    	DmsListElementOptions,
    } from "@whop/embedded-components-vanilla-js/types";

    const elements = loadWhopElements();

    async function getToken() {
    	const response = await fetch("/api/token");
    	const data = await response.json();
    	return data.token;
    }

    export function MessagesPage() {
    	const [channelId, setChannelId] = useState<string>();

    	const handleDmsEvent = useCallback((event: DmsListElementEvent) => {
    		switch (event.type) {
    			case "channelSelected":
    				setChannelId(event.detail.id);
    				break;
    		}
    	}, []);

    	const dmsOptions: DmsListElementOptions = useMemo(() => {
    		return {
    			selectedChannel: channelId,
    			onEvent: handleDmsEvent,
    		};
    	}, [channelId, handleDmsEvent]);

    	return (
    		<Elements elements={elements}>
    			<ChatSession token={getToken}>
    				<DmsListElement options={dmsOptions} />
    			</ChatSession>
    		</Elements>
    	);
    }
    ```
  </Platform>

  <Platform value="vanillajs">
    ```typescript theme={null}
    import { loadWhopElements } from "@whop/embedded-components-vanilla-js";

    async function getToken() {
    	const response = await fetch("/api/token");
    	const data = await response.json();
    	return data.token;
    }

    const whopElements = await loadWhopElements();

    const session = whopElements.createChatSession({
    	token: getToken,
    });

    const dmsListElement = session.createElement("dms-list-element", {});

    dmsListElement.on("channelSelected", (ev) => {
    	console.log("Channel selected:", ev.detail.id);
    });

    dmsListElement.mount("#dms-list-container");
    ```
  </Platform>

  <Platform value="swift">
    Display a list of the user's direct messages with `WhopDMsListView`. Listen for channel selection to navigate into a conversation.

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

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

  ### Company scoping

  Filter the DMs list to only show conversations belonging to a specific company by passing a `companyId`. To programmatically create DM channels, use the [Create DM Channel](/api-reference/dm-channels/create-dm-channel) endpoint — make sure to pass the same `companyId` so the channel appears in the scoped list.

  <Platform value="react">
    ```tsx theme={null}
    const dmsOptions: DmsListElementOptions = useMemo(() => {
    	return {
    		companyId: "biz_xxxx",
    		selectedChannel: channelId,
    		onEvent: handleDmsEvent,
    	};
    }, [channelId, handleDmsEvent]);

    return (
    	<Elements elements={elements}>
    		<ChatSession token={getToken}>
    			<DmsListElement options={dmsOptions} />
    		</ChatSession>
    	</Elements>
    );
    ```
  </Platform>

  <Platform value="vanillajs">
    ```typescript theme={null}
    const dmsListElement = session.createElement("dms-list-element", {
    	companyId: "biz_xxxx",
    });

    dmsListElement.mount("#dms-list-container");
    ```
  </Platform>

  <Platform value="swift">
    ```swift theme={null}
    WhopDMsListView(
        companyId: "biz_xxxx",
        onEvent: { event in
            switch event {
            case let .channelSelected(channel):
                selectedChannel = channel
            }
        }
    )
    ```
  </Platform>

  ### Event handling

  <Platform value="react">
    Listen for channel selection to open the corresponding chat view.

    | Event             | Detail           | Description                            |
    | ----------------- | ---------------- | -------------------------------------- |
    | `channelSelected` | `{ id: string }` | Emitted when the user clicks a channel |

    ```tsx theme={null}
    const handleDmsEvent = useCallback((event: DmsListElementEvent) => {
    	switch (event.type) {
    		case "channelSelected":
    			setChannelId(event.detail.id);
    			break;
    	}
    }, []);
    ```
  </Platform>

  <Platform value="vanillajs">
    Listen for channel selection to open the corresponding chat view.

    | Event             | Detail           | Description                            |
    | ----------------- | ---------------- | -------------------------------------- |
    | `channelSelected` | `{ id: string }` | Emitted when the user clicks a channel |

    ```typescript theme={null}
    dmsListElement.on("channelSelected", (ev) => {
    	console.log("Channel selected:", ev.detail.id);
    });
    ```
  </Platform>

  <Platform value="swift">
    On iOS, channel selection is handled by navigating to a new view. Use the `.channelSelected` event to push a `WhopChatView` onto the navigation stack.

    | Event              | Detail               | Description                          |
    | ------------------ | -------------------- | ------------------------------------ |
    | `.channelSelected` | `channel: DMChannel` | Emitted when the user taps a channel |

    ```swift theme={null}
    WhopDMsListView(
        onEvent: { event in
            switch event {
            case let .channelSelected(channel):
                selectedChannel = channel
            }
        }
    )
    .navigationDestination(item: $selectedChannel) { channel in
        WhopChatView(
            channelId: channel.id,
            style: .imessage
        )
        .navigationBarTitleDisplayMode(.inline)
        .navigationTitle(channel.name)
    }
    ```
  </Platform>
</PlatformSelect>
