Skip to content
Draft
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
5 changes: 5 additions & 0 deletions build-tools/utils/custom-css-properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ const customCssPropertiesList = [
'promptInputStylePlaceholderFontSize',
'promptInputStylePlaceholderFontStyle',
'promptInputStylePlaceholderFontWeight',
// Prompt input menu/dropdown style properties
'promptInputMenuStyleBackgroundColor',
'promptInputMenuStyleBorderColor',
'promptInputMenuStyleBorderRadius',
'promptInputMenuStyleBorderWidth',
// Progress bar style properties
'progressBarBackgroundColor',
'progressBarBorderRadius',
Expand Down
48 changes: 48 additions & 0 deletions pages/prompt-input/menu-style.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useState } from 'react';

import PromptInput, { PromptInputProps } from '~components/prompt-input';

const menuStyle: PromptInputProps.Style['menu'] = {
backgroundColor: 'light-dark(#faf5ff, #2d1b4e)',
borderColor: '#a78bfa',
borderRadius: '12px',
borderWidth: '1.5px',
};

const options: PromptInputProps.MenuDefinition['options'] = [
{ value: 'help', label: '/help', description: 'Show help' },
{ value: 'search', label: '/search', description: 'Search content' },
{ value: 'clear', label: '/clear', description: 'Clear the input' },
];

export default function MenuStylePage() {
const [value, setValue] = useState('');
const [tokens, setTokens] = useState<readonly PromptInputProps.InputToken[]>([]);

return (
<>
<h1>PromptInput — menu style override</h1>
<p>
Type <code>/</code> to open the command menu. The dropdown uses the custom <code>style.menu</code> overrides
(purple border, rounded corners, themed background).
</p>
<PromptInput
ariaLabel="Prompt input with styled menu"
value={value}
tokens={tokens}
menus={[{ id: 'commands', trigger: '/', options, filteringType: 'auto' }]}
style={{ menu: menuStyle }}
onChange={({ detail }) => {
setValue(detail.value);
if (detail.tokens) {
setTokens(detail.tokens);
}
}}
onAction={() => {}}
i18nStrings={{ actionButtonAriaLabel: 'Send' }}
/>
</>
);
}
10 changes: 10 additions & 0 deletions src/prompt-input/__tests__/styles.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ describe('getPromptInputStyles', () => {
fontWeight: '400',
fontStyle: 'italic',
},
menu: {
backgroundColor: '#1a1a2e',
borderColor: '#7b2d8b',
borderRadius: '12px',
borderWidth: '1.5px',
},
};

expect(getPromptInputStyles(allStyles)).toEqual({
Expand Down Expand Up @@ -93,6 +99,10 @@ describe('getPromptInputStyles', () => {
[customCssProps.promptInputStylePlaceholderFontSize]: '14px',
[customCssProps.promptInputStylePlaceholderFontWeight]: '400',
[customCssProps.promptInputStylePlaceholderFontStyle]: 'italic',
[customCssProps.promptInputMenuStyleBackgroundColor]: '#1a1a2e',
[customCssProps.promptInputMenuStyleBorderColor]: '#7b2d8b',
[customCssProps.promptInputMenuStyleBorderRadius]: '12px',
[customCssProps.promptInputMenuStyleBorderWidth]: '1.5px',
});
});

Expand Down
16 changes: 16 additions & 0 deletions src/prompt-input/components/token-mode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import React from 'react';
import clsx from 'clsx';

import { DropdownProps } from '../../dropdown/interfaces';
import Dropdown from '../../dropdown/internal';
import DropdownFooter from '../../internal/components/dropdown-footer';
import { DropdownStatusResult } from '../../internal/components/dropdown-status';
Expand Down Expand Up @@ -53,6 +54,7 @@ interface TokenModeProps {
i18nStrings?: PromptInputProps['i18nStrings'];

maxMenuHeight?: number;
menuStyle?: PromptInputProps.Style['menu'];
}

const MENU_MIN_WIDTH = 300;
Expand All @@ -76,6 +78,7 @@ export default function TokenMode({
menuItemsHandlers,
menuDropdownStatus,
maxMenuHeight,
menuStyle,
handleInput,
handleLoadMore,
editableElementAttributes,
Expand Down Expand Up @@ -117,6 +120,19 @@ export default function TokenMode({
minWidth={MENU_MIN_WIDTH}
maxHeight={maxMenuHeight}
expandToViewport={true}
style={
menuStyle
? ({
// DropdownProps.Style names the fill `background`; PromptInput exposes it as `backgroundColor`.
dropdown: {
background: menuStyle.backgroundColor,
borderColor: menuStyle.borderColor,
borderRadius: menuStyle.borderRadius,
borderWidth: menuStyle.borderWidth,
},
} satisfies DropdownProps.Style)
: undefined
}
open={
!!(
shouldRenderMenuDropdown &&
Expand Down
13 changes: 13 additions & 0 deletions src/prompt-input/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,5 +574,18 @@ export namespace PromptInputProps {
fontStyle?: string;
fontWeight?: string;
};
/**
* Style overrides for the menus/shortcuts dropdown that appears when a trigger
* character is typed. Use this to match the dropdown's visual appearance to a
* custom design system theme.
*
* @awsuiSystem core
*/
menu?: {
backgroundColor?: string;
borderColor?: string;
borderRadius?: string;
borderWidth?: string;
};
}
}
1 change: 1 addition & 0 deletions src/prompt-input/internal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ const InternalPromptInput = React.forwardRef(
menuItemsHandlers={tokenMode.menuItemsHandlers}
menuDropdownStatus={tokenMode.menuDropdownStatus}
maxMenuHeight={maxMenuHeight}
menuStyle={style?.menu}
handleInput={tokenMode.handleInput}
handleLoadMore={tokenMode.handleLoadMore}
editableElementAttributes={tokenMode.editableElementAttributes}
Expand Down
4 changes: 4 additions & 0 deletions src/prompt-input/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,9 @@ export function getPromptInputStyles(style: PromptInputProps['style']) {
[customCssProps.promptInputStylePlaceholderFontSize]: style?.placeholder?.fontSize,
[customCssProps.promptInputStylePlaceholderFontWeight]: style?.placeholder?.fontWeight,
[customCssProps.promptInputStylePlaceholderFontStyle]: style?.placeholder?.fontStyle,
[customCssProps.promptInputMenuStyleBackgroundColor]: style?.menu?.backgroundColor,
[customCssProps.promptInputMenuStyleBorderColor]: style?.menu?.borderColor,
[customCssProps.promptInputMenuStyleBorderRadius]: style?.menu?.borderRadius,
[customCssProps.promptInputMenuStyleBorderWidth]: style?.menu?.borderWidth,
};
}
Loading