Skip to content

Commit

Permalink
chore(ai): add theming for AIConversation (#5827)
Browse files Browse the repository at this point in the history
  • Loading branch information
dbanksdesign authored Oct 15, 2024
1 parent 1421dde commit ac7cb27
Show file tree
Hide file tree
Showing 13 changed files with 702 additions and 38 deletions.
30 changes: 30 additions & 0 deletions .changeset/pretty-items-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
"@aws-amplify/ui": patch
---

chore(ai): add theming for AIConversation

```ts
const theme = createTheme({
tokens: {
components: {
aiConversation: {}
}
}
})
```

```ts
const aiConversationTheme = defineComponentTheme({
name: 'ai-conversation',
theme(tokens) {
return {
_element: {
message: {
color: tokens.colors.font.tertiary
}
}
}
}
});
```
140 changes: 140 additions & 0 deletions docs/__tests__/__snapshots__/cssvars-table.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,146 @@ exports[`CSS Variables Table 1`] = `
"variable": "--amplify-components-accordion-item-trigger-padding-inline",
"value": "var(--amplify-space-small)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-border-color",
"value": "var(--amplify-colors-border-secondary)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-border-radius",
"value": "var(--amplify-radii-small)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-border-width",
"value": "var(--amplify-border-widths-small)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-font-size",
"value": "var(--amplify-font-sizes-small)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-gap",
"value": "var(--amplify-space-xs)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-image-height",
"value": "var(--amplify-font-sizes-medium)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-image-width",
"value": "var(--amplify-font-sizes-medium)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-list-gap",
"value": "var(--amplify-space-xxs)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-list-padding-block-start",
"value": "var(--amplify-space-xs)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-name-color",
"value": "var(--amplify-colors-font-primary)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-name-font-size",
"value": "var(--amplify-font-sizes-small)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-name-font-weight",
"value": "var(--amplify-font-weights-normal)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-padding-block",
"value": "var(--amplify-space-xxxs)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-padding-inline",
"value": "var(--amplify-space-xs)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-remove-padding",
"value": "var(--amplify-space-xxs)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-size-color",
"value": "var(--amplify-colors-font-tertiary)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-size-font-size",
"value": "var(--amplify-font-sizes-small)"
},
{
"variable": "--amplify-components-ai-conversation-attachment-size-font-weight",
"value": "var(--amplify-font-weights-normal)"
},
{
"variable": "--amplify-components-ai-conversation-form-gap",
"value": "var(--amplify-space-small)"
},
{
"variable": "--amplify-components-ai-conversation-form-padding",
"value": "var(--amplify-space-small)"
},
{
"variable": "--amplify-components-ai-conversation-message-assistant-background-color",
"value": "var(--amplify-colors-primary-10)"
},
{
"variable": "--amplify-components-ai-conversation-message-background-color",
"value": "var(--amplify-colors-background-secondary)"
},
{
"variable": "--amplify-components-ai-conversation-message-body-gap",
"value": "var(--amplify-space-xs)"
},
{
"variable": "--amplify-components-ai-conversation-message-border-radius",
"value": "var(--amplify-radii-large)"
},
{
"variable": "--amplify-components-ai-conversation-message-gap",
"value": "var(--amplify-space-small)"
},
{
"variable": "--amplify-components-ai-conversation-message-padding-block",
"value": "var(--amplify-space-small)"
},
{
"variable": "--amplify-components-ai-conversation-message-padding-inline",
"value": "var(--amplify-space-small)"
},
{
"variable": "--amplify-components-ai-conversation-message-sender-gap",
"value": "var(--amplify-space-small)"
},
{
"variable": "--amplify-components-ai-conversation-message-sender-timestamp-color",
"value": "var(--amplify-colors-font-tertiary)"
},
{
"variable": "--amplify-components-ai-conversation-message-sender-timestamp-font-size",
"value": "inherit"
},
{
"variable": "--amplify-components-ai-conversation-message-sender-timestamp-font-weight",
"value": "inherit"
},
{
"variable": "--amplify-components-ai-conversation-message-sender-username-color",
"value": "var(--amplify-colors-font-primary)"
},
{
"variable": "--amplify-components-ai-conversation-message-sender-username-font-size",
"value": "inherit"
},
{
"variable": "--amplify-components-ai-conversation-message-sender-username-font-weight",
"value": "var(--amplify-font-weights-bold)"
},
{
"variable": "--amplify-components-ai-conversation-message-user-background-color",
"value": "var(--amplify-colors-background-secondary)"
},
{
"variable": "--amplify-components-alert-align-items",
"value": "center"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import amplifyOutputs from '@environments/ai/gen2/amplify_outputs';
export default amplifyOutputs;
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import * as React from 'react';

import { Amplify } from 'aws-amplify';
import { generateClient } from 'aws-amplify/api';
import {
View,
createTheme,
defaultDarkModeOverride,
withAuthenticator,
ColorMode,
Button,
} from '@aws-amplify/ui-react';
import { createAIHooks, AIConversation } from '@aws-amplify/ui-react-ai';
import { ThemeStyle, defineComponentTheme } from '@aws-amplify/ui-react/server';
import '@aws-amplify/ui-react/styles.css';

import outputs from './amplify_outputs';
import type { Schema } from '@environments/ai/gen2/amplify/data/resource';

const client = generateClient<Schema>({ authMode: 'userPool' });
const { useAIConversation } = createAIHooks(client);

Amplify.configure(outputs);

const conversationTheme = defineComponentTheme({
name: 'ai-conversation',
theme(tokens) {
return {
_element: {
message: {
borderRadius: tokens.radii.large,
padding: tokens.space.small,
borderWidth: tokens.borderWidths.small,
borderStyle: 'solid',
borderColor: tokens.colors.border.primary,
boxShadow: `${tokens.shadows.medium}`,
},
message__list: {
gap: tokens.space.large,
},
form: {
borderRadius: tokens.radii.large,
padding: tokens.space.small,
borderWidth: tokens.borderWidths.small,
borderStyle: 'solid',
borderColor: tokens.colors.border.primary,
boxShadow: `${tokens.shadows.medium}`,
},
},
};
},
overrides: [
{
colorMode: 'dark',
theme(tokens) {
return {
_element: {
form: {
backgroundColor: tokens.colors.background.secondary,
},
},
};
},
},
],
});

const theme = createTheme({
name: 'ai-conversation-theme',
components: [conversationTheme],
overrides: [defaultDarkModeOverride],
});

function Chat() {
const [
{
data: { messages },
isLoading,
},
sendMessage,
] = useAIConversation('pirateChat');
return (
<>
<AIConversation
messages={messages}
handleSendMessage={sendMessage}
isLoading={isLoading}
/>
<AIConversation
messages={messages}
handleSendMessage={sendMessage}
isLoading={isLoading}
variant="bubble"
/>
</>
);
}

function AIConversationThemePage() {
const [colorMode, setColorMode] = React.useState<ColorMode>('light');

return (
<>
<Button
onClick={() => {
setColorMode((prevColorMode) =>
prevColorMode === 'dark' ? 'light' : 'dark'
);
}}
>
{colorMode}
</Button>
<View
backgroundColor="background.primary"
{...theme.containerProps({ colorMode })}
>
<Chat />
</View>
<ThemeStyle theme={theme} />
</>
);
}

export default withAuthenticator(AIConversationThemePage);
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import amplifyOutputs from '@environments/ai/gen2/amplify_outputs';
export default amplifyOutputs;
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import * as React from 'react';
import { Amplify } from 'aws-amplify';
import { createAIHooks, AIConversation } from '@aws-amplify/ui-react-ai';
import { ThemeStyle } from '@aws-amplify/ui-react/server';
import { generateClient } from 'aws-amplify/api';
import '@aws-amplify/ui-react/styles.css';
import outputs from './amplify_outputs';
import type { Schema } from '@environments/ai/gen2/amplify/data/resource';
import {
View,
createTheme,
defaultDarkModeOverride,
withAuthenticator,
} from '@aws-amplify/ui-react';
import { ColorMode } from '@aws-amplify/ui-react';
import { Button } from '@aws-amplify/ui-react';

const client = generateClient<Schema>({ authMode: 'userPool' });
const { useAIConversation } = createAIHooks(client);

Amplify.configure(outputs);

const theme = createTheme({
name: 'ai-conversation-theme',
tokens: {
components: {
aiConversation: {
message: {
backgroundColor: { value: '#f5f5f5' },
gap: '{space.small}',
},
},
},
},
overrides: [defaultDarkModeOverride],
});

function AIConversationThemePage() {
const [colorMode, setColorMode] = React.useState<ColorMode>('light');
const [
{
data: { messages },
isLoading,
},
sendMessage,
] = useAIConversation('pirateChat');

return (
<>
<Button
onClick={() => {
setColorMode((prevColorMode) =>
prevColorMode === 'dark' ? 'light' : 'dark'
);
}}
>
{colorMode}
</Button>
<View
backgroundColor="background.primary"
{...theme.containerProps({ colorMode })}
>
<AIConversation
messages={messages}
handleSendMessage={sendMessage}
isLoading={isLoading}
allowAttachments
/>
<AIConversation
messages={messages}
handleSendMessage={sendMessage}
isLoading={isLoading}
variant="bubble"
/>
</View>
<ThemeStyle theme={theme} />
</>
);
}

export default withAuthenticator(AIConversationThemePage);
Loading

0 comments on commit ac7cb27

Please sign in to comment.