@trycourier/courier-ui-inbox
Version:
Inbox components for the Courier web UI
381 lines (276 loc) • 10.7 kB
Markdown
<img width="1040" alt="courier-ui-inbox" src="https://github.com/user-attachments/assets/6227249b-d008-4719-bddc-874f34432376" />
## 1. Install
```sh
npm install @trycourier/courier-ui-inbox
```
> **Using React?** We suggest you use [@trycourier/courier-react](../courier-react/README.md) package instead.
## 2. Authenticate
To use the SDK, you need to generate a JWT (JSON Web Token) for your user. **This JWT should always be generated by your backend server, never in client-side code.**
**How it works:**
1. **Your frontend calls your backend:**
- When your app needs to authenticate a user, your frontend should make a request to your own backend (e.g., `/api/generate-courier-jwt`).
2. **Your backend calls Courier to issue a JWT:**
- In your backend endpoint, use your [Courier API Key](https://app.courier.com/settings/api-keys) to call the [Courier JWT Token Endpoint](https://www.courier.com/docs/reference/auth/issue-token) and generate a JWT for the user.
- Your backend then returns the JWT to your frontend.
To quickly test JWT generation (for development only), you can use the following cURL command to call Courier's API directly. **Do not use this in production or from client-side code.**
```sh
curl --request POST \
--url https://api.courier.com/auth/issue-token \
--header 'Accept: application/json' \
--header 'Authorization: Bearer $YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data \
'{
"scope": "user_id:$YOUR_USER_ID write:user-tokens inbox:read:messages inbox:write:events read:preferences write:preferences read:brands",
"expires_in": "$YOUR_NUMBER days"
}'
```
## 3. Add Inbox Component
### `courier-inbox`
<img width="688" alt="Screenshot 2025-06-25 at 2 32 30 PM" src="https://github.com/user-attachments/assets/93246c34-3c5a-475e-8e83-7df6acf9bdf3" />
```html
<body>
<courier-inbox id="inbox"></courier-inbox>
<script type="module">
import { Courier } from '@trycourier/courier-ui-inbox';
// Generate a JWT for your user (do this on your backend server)
const jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'; // Replace with actual JWT
// Authenticate the user with the inbox
Courier.shared.signIn({
userId: $YOUR_USER_ID,
jwt: jwt
});
</script>
</body>
```
### `courier-inbox-popup-menu`
<img width="602" alt="Screenshot 2025-06-25 at 2 33 17 PM" src="https://github.com/user-attachments/assets/c3b7f4cc-26c1-4be6-9ed5-a3fc3c0b335b" />
```html
<body>
<div style="padding: 24px;">
<courier-inbox-popup-menu id="inbox"></courier-inbox-popup-menu>
</div>
<script type="module">
import { Courier } from '@trycourier/courier-ui-inbox';
// Generate a JWT for your user (do this on your backend server)
const jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'; // Replace with actual JWT
// Authenticate the user with the inbox
Courier.shared.signIn({
userId: $YOUR_USER_ID,
jwt: jwt
});
</script>
</body>
```
## Handle Clicks and Presses
```html
<body>
<courier-inbox id="inbox"></courier-inbox> <!-- or use courier-inbox-popup-menu -->
<script type="module">
import { Courier } from '@trycourier/courier-ui-inbox';
// Generate a JWT for your user (do this on your backend server)
const jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'; // Replace with actual JWT
// Authenticate the user with the inbox
Courier.shared.signIn({
userId: $YOUR_USER_ID,
jwt: jwt
});
// Reference the element
const inbox = document.getElementById('inbox');
// Handle message clicks
inbox.onMessageClick(({ message, index }) => {
alert("Message clicked at index " + index + ":\n" + JSON.stringify(message, null, 2));
});
// Handle message action clicks (These are buttons on individial messages)
inbox.onMessageActionClick(({ message, action, index }) => {
alert(
"Message action clicked at index " + index + ":\n" +
"Action: " + JSON.stringify(action, null, 2) + "\n" +
"Message: " + JSON.stringify(message, null, 2)
);
});
// Handle message long presses. **Only works on devices that support javascript's touch events. This will not work with a mouse cursor.**
inbox.onMessageLongPress(({ message, index }) => {
alert("Message long pressed at index " + index + ":\n" + JSON.stringify(message, null, 2));
});
</script>
</body>
```
## Styles and Theming
### Light & Dark Themes
The fastest way to style the Inbox to match your app. This example shows unread indicator styling, but you can customize fonts, icons, text, and more.
> **🎨 Theme Reference:** [All available theme values](./docs/theme.md)
<img width="688" alt="Screenshot 2025-06-25 at 2 36 20 PM" src="https://github.com/user-attachments/assets/982164fe-fe0d-4e66-82d1-b5a6571f1aa4" />
```html
<body>
<courier-inbox id="inbox"></courier-inbox> <!-- or use courier-inbox-popup-menu -->
<script type="module">
...
// Reference the element
const inbox = document.getElementById('inbox');
const theme = {
inbox: {
header: {
filters: {
unreadIndicator: {
backgroundColor: "#8B5CF6"
}
}
},
list: {
item: {
unreadIndicatorColor: "#8B5CF6"
}
}
}
}
// Set the theme
inbox.setLightTheme(theme);
inbox.setDarkTheme(theme);
// Set the mode
// This will force light, dark or system theme mode
inbox.setMode('light');
</script>
</body>
```
### Popup Alignment, Positioning, and Dimensions
```html
<body>
<div style="display: flex; justify-content: center; align-items: center; padding: 100px;">
<!-- Available alignments: 'top-right' | 'top-left' | 'top-center' | 'bottom-right' | 'bottom-left' | 'bottom-center' | 'center-right' | 'center-left' | 'center-center' -->
<courier-inbox-popup-menu
popup-alignment="top-right"
top="44px"
right="44px"
popup-width="340px"
popup-height="400px">
</courier-inbox-popup-menu>
</div>
...
</body>
```
### Custom height `courier-inbox`
> **Important:** The default `courier-inbox` height is auto. It will set it's height based on it's children.
```html
<body>
<courier-inbox height="50vh"></courier-inbox>
...
</body>
```
## Custom Elements
Customize the inbox UI with any element you want.
### List Items
<img width="688" alt="Screenshot 2025-06-25 at 2 37 29 PM" src="https://github.com/user-attachments/assets/53da26d1-ed9a-461d-ad92-2e74ee3e91bf" />
```html
<body>
<courier-inbox id="inbox"></courier-inbox> <!-- or use courier-inbox-popup-menu -->
<script type="module">
...
// Reference the courier-inbox element
const inbox = document.getElementById('inbox');
// Set a custom list item
inbox.setListItem(({ message, index }) => {
const pre = document.createElement('pre');
pre.style.padding = '24px';
pre.style.borderBottom = '1px solid #e0e0e0';
pre.style.margin = '0';
pre.textContent = JSON.stringify(({ message, index }), null, 2);
return pre;
});
</script>
</body>
```
### Header
<img width="688" alt="Screenshot 2025-06-25 at 2 38 45 PM" src="https://github.com/user-attachments/assets/d393f77d-695e-4fed-a60a-7f7b59909772" />
```html
<body>
<courier-inbox id="inbox"></courier-inbox> <!-- or use courier-inbox-popup-menu -->
<script type="module">
...
// Reference the courier-inbox element
const inbox = document.getElementById('inbox');
// Remove the header
inbox.removeHeader();
// Set a custom header
inbox.setHeader(({ feedType, unreadCount, messageCount }) => {
const headerDiv = document.createElement('div');
headerDiv.style.background = 'red';
headerDiv.style.fontSize = '24px';
headerDiv.style.padding = '24px';
headerDiv.style.width = '100%';
headerDiv.textContent = feedType;
return headerDiv;
});
// Change the feed type
// "inbox" and "archive" are available
inbox.setFeedType('archive');
</script>
</body>
```
### Popup Menu Button
<img width="688" alt="Screenshot 2025-06-25 at 2 39 49 PM" src="https://github.com/user-attachments/assets/5eeb32ae-13ff-4622-b6ea-b302f04509f3" />
```html
<body>
<div style="display: flex; justify-content: center; align-items: center; padding: 100px;">
<courier-inbox-popup-menu id="inbox"></courier-inbox-popup-menu>
</div>
<script type="module">
...
// Reference the courier-inbox element
const inbox = document.getElementById('inbox');
// Set a custom menu button
inbox.setMenuButton(({ unreadCount }) => {
const button = document.createElement('button');
button.textContent = `Open the Inbox Popup. Unread message count: ${unreadCount}`;
return button;
});
</script>
</body>
```
### Loading, Empty, Error & Pagination
```html
<body>
<courier-inbox id="inbox"></courier-inbox> <!-- or use courier-inbox-popup-menu -->
<script type="module">
...
// Reference the courier-inbox element
const inbox = document.getElementById('inbox');
// Set a custom loading state
inbox.setLoadingState(props => {
const loading = document.createElement('div');
loading.style.padding = '24px';
loading.style.background = 'red';
loading.textContent = 'Custom Loading State';
return loading;
});
// Set a custom empty state
inbox.setEmptyState(props => {
const empty = document.createElement('div');
empty.style.padding = '24px';
empty.style.background = 'green';
empty.textContent = 'Custom Empty State';
return empty;
});
// Set a custom error state
inbox.setErrorState(props => {
const error = document.createElement('div');
error.style.padding = '24px';
error.style.background = 'blue';
error.textContent = 'Custom Error State';
return error;
});
// Set a custom pagination state
inbox.setPaginationItem(props => {
const pagination = document.createElement('div');
pagination.style.padding = '24px';
pagination.style.background = 'yellow';
pagination.textContent = 'Custom Pagination Item';
return pagination;
});
</script>
</body>
```
> **Using React?** We suggest you use [@trycourier/courier-react](../courier-react/README.md) package instead.
# **Share feedback with Courier**
We want to make this the best SDK for managing notifications! Have an idea or feedback about our SDKs? Let us know!
[Courier Web Issues](https://github.com/trycourier/courier-web/issues)