diff --git a/build-tools/utils/custom-css-properties.js b/build-tools/utils/custom-css-properties.js index 73511df043..cb51af6453 100644 --- a/build-tools/utils/custom-css-properties.js +++ b/build-tools/utils/custom-css-properties.js @@ -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', diff --git a/pages/prompt-input/menu-style.page.tsx b/pages/prompt-input/menu-style.page.tsx new file mode 100644 index 0000000000..ed707a5263 --- /dev/null +++ b/pages/prompt-input/menu-style.page.tsx @@ -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([]); + + return ( + <> +

PromptInput — menu style override

+

+ Type / to open the command menu. The dropdown uses the custom style.menu overrides + (purple border, rounded corners, themed background). +

+ { + setValue(detail.value); + if (detail.tokens) { + setTokens(detail.tokens); + } + }} + onAction={() => {}} + i18nStrings={{ actionButtonAriaLabel: 'Send' }} + /> + + ); +} diff --git a/src/prompt-input/__tests__/styles.test.tsx b/src/prompt-input/__tests__/styles.test.tsx index beee993c47..547b0ae51a 100644 --- a/src/prompt-input/__tests__/styles.test.tsx +++ b/src/prompt-input/__tests__/styles.test.tsx @@ -60,6 +60,12 @@ describe('getPromptInputStyles', () => { fontWeight: '400', fontStyle: 'italic', }, + menu: { + backgroundColor: '#1a1a2e', + borderColor: '#7b2d8b', + borderRadius: '12px', + borderWidth: '1.5px', + }, }; expect(getPromptInputStyles(allStyles)).toEqual({ @@ -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', }); }); diff --git a/src/prompt-input/components/token-mode.tsx b/src/prompt-input/components/token-mode.tsx index b5716048bc..c6aa8b3e45 100644 --- a/src/prompt-input/components/token-mode.tsx +++ b/src/prompt-input/components/token-mode.tsx @@ -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'; @@ -53,6 +54,7 @@ interface TokenModeProps { i18nStrings?: PromptInputProps['i18nStrings']; maxMenuHeight?: number; + menuStyle?: PromptInputProps.Style['menu']; } const MENU_MIN_WIDTH = 300; @@ -76,6 +78,7 @@ export default function TokenMode({ menuItemsHandlers, menuDropdownStatus, maxMenuHeight, + menuStyle, handleInput, handleLoadMore, editableElementAttributes, @@ -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 && diff --git a/src/prompt-input/interfaces.ts b/src/prompt-input/interfaces.ts index 36011abcee..ee7569a7e3 100644 --- a/src/prompt-input/interfaces.ts +++ b/src/prompt-input/interfaces.ts @@ -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; + }; } } diff --git a/src/prompt-input/internal.tsx b/src/prompt-input/internal.tsx index 4a042cc067..716e5e3c80 100644 --- a/src/prompt-input/internal.tsx +++ b/src/prompt-input/internal.tsx @@ -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} diff --git a/src/prompt-input/styles.tsx b/src/prompt-input/styles.tsx index f993af759d..ec7013277f 100644 --- a/src/prompt-input/styles.tsx +++ b/src/prompt-input/styles.tsx @@ -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, }; }