diff --git a/pages/autosuggest/style-permutations.page.tsx b/pages/autosuggest/style-permutations.page.tsx new file mode 100644 index 0000000000..2aa9e234c2 --- /dev/null +++ b/pages/autosuggest/style-permutations.page.tsx @@ -0,0 +1,106 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import React from 'react'; + +import Autosuggest, { AutosuggestProps } from '~components/autosuggest'; + +import createPermutations from '../utils/permutations'; +import PermutationsView from '../utils/permutations-view'; +import ScreenshotArea from '../utils/screenshot-area'; + +const style1 = { + root: { + borderColor: { + default: 'light-dark(#f59e0b, #fbbf24)', + hover: 'light-dark(#b45309, #fcd34d)', + focus: 'light-dark(#d97706, #fde047)', + disabled: 'light-dark(#fcd34d, #fef08a)', + readonly: 'light-dark(#fcd34d, #fef08a)', + }, + borderWidth: '2px', + borderRadius: '16px', + backgroundColor: { + default: 'light-dark(#fef3c7, #000000)', + hover: 'light-dark(#fefce8, #0a0a0a)', + focus: 'light-dark(#fef9c3, #0f0f0f)', + disabled: 'light-dark(#fcd34d, #1a1a1a)', + readonly: 'light-dark(#fef3c7, #0a0a0a)', + }, + boxShadow: { + default: '0 2px 8px rgba(245, 158, 11, 0.15)', + hover: '0 6px 16px rgba(245, 158, 11, 0.25)', + focus: '0 0 0 4px rgba(245, 158, 11, 0.25), 0 6px 16px rgba(245, 158, 11, 0.3)', + disabled: 'none', + readonly: '0 2px 8px rgba(245, 158, 11, 0.15)', + }, + color: { + default: 'light-dark(#78350f, #fef3c7)', + hover: 'light-dark(#78350f, #fef3c7)', + focus: 'light-dark(#78350f, #fef3c7)', + disabled: 'light-dark(#78350f, #fef3c7)', + readonly: 'light-dark(#92400e, #fde68a)', + }, + }, + placeholder: { + color: 'light-dark(black, white)', + }, +}; + +const enteredTextLabel = (value: string) => `Use: ${value}`; + +const permutations = createPermutations([ + { + value: ['This is a test value'], + disabled: [false, true], + invalid: [false, true], + warning: [false, true], + style: [style1], + options: [ + [ + { value: 'option1', label: 'Option 1' }, + { value: 'option2', label: 'Option 2' }, + ], + ], + enteredTextLabel: [enteredTextLabel], + }, + { + value: [''], + placeholder: ['Placeholder'], + disabled: [false, true], + invalid: [false, true], + warning: [false, true], + style: [style1], + options: [ + [ + { value: 'option1', label: 'Option 1' }, + { value: 'option2', label: 'Option 2' }, + ], + ], + enteredTextLabel: [enteredTextLabel], + }, +]); + +export default function AutosuggestStylePermutations() { + return ( + <> +

Autosuggest Style permutations

+ + ( +
+ { + /*empty handler to suppress react controlled property warning*/ + }} + {...permutation} + /> +
+ )} + /> +
+ + ); +} diff --git a/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap b/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap index 3e377e1fcd..2fb16d8b96 100644 --- a/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap +++ b/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap @@ -3555,6 +3555,236 @@ This is required to provide a good screen reader experience. For more informatio "optional": true, "type": "string", }, + { + "inlineType": { + "name": "AutosuggestProps.Style", + "properties": [ + { + "inlineType": { + "name": "object", + "properties": [ + { + "name": "color", + "optional": true, + "type": "string", + }, + { + "name": "fontSize", + "optional": true, + "type": "string", + }, + { + "name": "fontStyle", + "optional": true, + "type": "string", + }, + { + "name": "fontWeight", + "optional": true, + "type": "string", + }, + ], + "type": "object", + }, + "name": "placeholder", + "optional": true, + "type": "{ color?: string | undefined; fontSize?: string | undefined; fontStyle?: string | undefined; fontWeight?: string | undefined; }", + }, + { + "inlineType": { + "name": "object", + "properties": [ + { + "inlineType": { + "name": "object", + "properties": [ + { + "name": "default", + "optional": true, + "type": "string", + }, + { + "name": "disabled", + "optional": true, + "type": "string", + }, + { + "name": "focus", + "optional": true, + "type": "string", + }, + { + "name": "hover", + "optional": true, + "type": "string", + }, + { + "name": "readonly", + "optional": true, + "type": "string", + }, + ], + "type": "object", + }, + "name": "backgroundColor", + "optional": true, + "type": "{ default?: string | undefined; disabled?: string | undefined; focus?: string | undefined; hover?: string | undefined; readonly?: string | undefined; }", + }, + { + "inlineType": { + "name": "object", + "properties": [ + { + "name": "default", + "optional": true, + "type": "string", + }, + { + "name": "disabled", + "optional": true, + "type": "string", + }, + { + "name": "focus", + "optional": true, + "type": "string", + }, + { + "name": "hover", + "optional": true, + "type": "string", + }, + { + "name": "readonly", + "optional": true, + "type": "string", + }, + ], + "type": "object", + }, + "name": "borderColor", + "optional": true, + "type": "{ default?: string | undefined; disabled?: string | undefined; focus?: string | undefined; hover?: string | undefined; readonly?: string | undefined; }", + }, + { + "name": "borderRadius", + "optional": true, + "type": "string", + }, + { + "name": "borderWidth", + "optional": true, + "type": "string", + }, + { + "inlineType": { + "name": "object", + "properties": [ + { + "name": "default", + "optional": true, + "type": "string", + }, + { + "name": "disabled", + "optional": true, + "type": "string", + }, + { + "name": "focus", + "optional": true, + "type": "string", + }, + { + "name": "hover", + "optional": true, + "type": "string", + }, + { + "name": "readonly", + "optional": true, + "type": "string", + }, + ], + "type": "object", + }, + "name": "boxShadow", + "optional": true, + "type": "{ default?: string | undefined; disabled?: string | undefined; focus?: string | undefined; hover?: string | undefined; readonly?: string | undefined; }", + }, + { + "inlineType": { + "name": "object", + "properties": [ + { + "name": "default", + "optional": true, + "type": "string", + }, + { + "name": "disabled", + "optional": true, + "type": "string", + }, + { + "name": "focus", + "optional": true, + "type": "string", + }, + { + "name": "hover", + "optional": true, + "type": "string", + }, + { + "name": "readonly", + "optional": true, + "type": "string", + }, + ], + "type": "object", + }, + "name": "color", + "optional": true, + "type": "{ default?: string | undefined; disabled?: string | undefined; focus?: string | undefined; hover?: string | undefined; readonly?: string | undefined; }", + }, + { + "name": "fontSize", + "optional": true, + "type": "string", + }, + { + "name": "fontWeight", + "optional": true, + "type": "string", + }, + { + "name": "paddingBlock", + "optional": true, + "type": "string", + }, + { + "name": "paddingInline", + "optional": true, + "type": "string", + }, + ], + "type": "object", + }, + "name": "root", + "optional": true, + "type": "{ backgroundColor?: { default?: string | undefined; disabled?: string | undefined; focus?: string | undefined; hover?: string | undefined; readonly?: string | undefined; } | undefined; ... 8 more ...; paddingInline?: string | undefined; }", + }, + ], + "type": "object", + }, + "name": "style", + "optional": true, + "systemTags": [ + "core", + ], + "type": "AutosuggestProps.Style", + }, { "description": "Specifies the text entered into the form element.", "name": "value", diff --git a/src/autosuggest/interfaces.ts b/src/autosuggest/interfaces.ts index 4237abb348..892b1ed9fb 100644 --- a/src/autosuggest/interfaces.ts +++ b/src/autosuggest/interfaces.ts @@ -125,6 +125,11 @@ export interface AutosuggestProps * [accessibility guidelines](/components/autosuggest/?tabId=usage#accessibility-guidelines). */ renderHighlightedAriaLive?: AutosuggestProps.ContainingOptionAndGroupString; + + /** + * @awsuiSystem core + */ + style?: AutosuggestProps.Style; } export namespace AutosuggestProps { @@ -160,6 +165,51 @@ export namespace AutosuggestProps { */ select(): void; } + + export interface Style { + root?: { + backgroundColor?: { + default?: string; + disabled?: string; + focus?: string; + hover?: string; + readonly?: string; + }; + borderColor?: { + default?: string; + disabled?: string; + focus?: string; + hover?: string; + readonly?: string; + }; + borderRadius?: string; + borderWidth?: string; + boxShadow?: { + default?: string; + disabled?: string; + focus?: string; + hover?: string; + readonly?: string; + }; + color?: { + default?: string; + disabled?: string; + focus?: string; + hover?: string; + readonly?: string; + }; + fontSize?: string; + fontWeight?: string; + paddingBlock?: string; + paddingInline?: string; + }; + placeholder?: { + color?: string; + fontSize?: string; + fontStyle?: string; + fontWeight?: string; + }; + } } // TODO: use DropdownOption type same as in select and multiselect diff --git a/src/autosuggest/internal.tsx b/src/autosuggest/internal.tsx index 60e4f045cf..60bbf09475 100644 --- a/src/autosuggest/internal.tsx +++ b/src/autosuggest/internal.tsx @@ -59,6 +59,7 @@ const InternalAutosuggest = React.forwardRef((props: InternalAutosuggestProps, r expandToViewport, onSelect, renderHighlightedAriaLive, + style, __internalRootRef, ...restProps } = props; @@ -223,6 +224,7 @@ const InternalAutosuggest = React.forwardRef((props: InternalAutosuggestProps, r ariaControls={listId} ariaActivedescendant={highlightedOptionId} dropdownExpanded={shouldRenderDropdownContent} + style={style} dropdownContent={ shouldRenderDropdownContent && ( void; onPressArrowUp?: () => void; onPressEnter?: () => boolean; + style?: InputProps['style']; } interface AutosuggestInputFocusOptions { @@ -94,6 +96,7 @@ const AutosuggestInput = React.forwardRef( onPressArrowDown, onPressArrowUp, onPressEnter, + style, __internalRootRef, ...restProps }: AutosuggestInputProps, @@ -306,6 +309,7 @@ const AutosuggestInput = React.forwardRef( autoComplete={false} nativeInputAttributes={processAttributes(nativeAttributes, nativeInputAttributes, 'Autosuggest')} __skipNativeAttributesWarnings={Object.keys(nativeAttributes)} + style={style} {...formFieldContext} /> } diff --git a/src/internal/styles/forms/mixins.scss b/src/internal/styles/forms/mixins.scss index a7631951a3..e2fcd389da 100644 --- a/src/internal/styles/forms/mixins.scss +++ b/src/internal/styles/forms/mixins.scss @@ -193,24 +193,32 @@ @include typography.font-body-s; } -@mixin form-invalid-control($color: awsui.$color-text-status-error, $border-color: awsui.$color-text-status-error) { +@mixin form-invalid-control( + $color: awsui.$color-text-status-error, + $border-color: awsui.$color-text-status-error, + $focus-box-shadow: foundation.$box-shadow-focused-light-invalid +) { color: $color; border-color: $border-color; padding-inline-start: constants.$invalid-control-left-padding; border-inline-start-width: constants.$invalid-control-left-border; &:focus { - box-shadow: foundation.$box-shadow-focused-light-invalid; + box-shadow: $focus-box-shadow; } @content; } -@mixin form-warning-control($color: awsui.$color-text-status-warning, $border-color: awsui.$color-text-status-warning) { +@mixin form-warning-control( + $color: awsui.$color-text-status-warning, + $border-color: awsui.$color-text-status-warning, + $focus-box-shadow: foundation.$box-shadow-focused-light-invalid +) { color: $color; border-color: $border-color; padding-inline-start: constants.$invalid-control-left-padding; border-inline-start-width: constants.$invalid-control-left-border; &:focus { - box-shadow: foundation.$box-shadow-focused-light-invalid; + box-shadow: $focus-box-shadow; } @content; }