Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add PromptInput component #2298

Merged
merged 33 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
e151ccb
chore: Initial component setup
May 21, 2024
e628c81
chore: Rename some files
May 27, 2024
02d25b0
feat: Add customizable icon and clean up interface
Jun 6, 2024
695aa7e
chore: Clean up styles and files
Jun 7, 2024
6335794
chore: Fix interface
timogasda Jun 11, 2024
bc86469
Add snapshot update
timogasda Jun 11, 2024
0f1fd8d
Update demo
timogasda Jun 11, 2024
727def7
Prevent icon from overlapping input text
gethinwebster Jun 12, 2024
5061c65
feat: Adds checkboxes for different states
Jun 24, 2024
ffb678b
feat: Adds urlParams
Jun 24, 2024
2e44975
fix: Fix icon not showing up in safari / firefox
Jun 24, 2024
67b9a6d
fix: Adds error aria label
Jun 24, 2024
4ae2bcc
chore: Adds basic tests
Jun 24, 2024
cdbbc3c
chore: Adds a11y tests
Jun 25, 2024
838bf57
chore: Adds tests to action button
Jun 25, 2024
dbe06fd
chore: Adds integ test, event tests, and support for rtl in send icon
Jun 25, 2024
ffe0c04
chore: Updating prompt input form submit test
Jun 25, 2024
1e84d99
feat: Adds url and svg properties, updates form test, and adds permut…
Jun 27, 2024
028d0df
fix: Fixes form submit behavior
Jun 27, 2024
dcce827
chore: Adds more tests
Jun 28, 2024
a25c8b2
chore: Adds test for disableAutoCorrect
Jul 1, 2024
bc06aba
chore: Move to internal file
Jul 1, 2024
b5c8972
fix: Fixes tests
Jul 1, 2024
5783d5a
chore: Updates snapshot tests
Jul 1, 2024
45d2477
fix: Adds iconAlt property, ref check, removes font load
Jul 2, 2024
21638c6
chore: Updates documenter
Jul 2, 2024
15e14b7
fix: Fix a11y test
Jul 2, 2024
c9f6695
fix: Updates from PR comments
Jul 8, 2024
0b3000a
feat: Adds select method
Jul 8, 2024
3b2cc8e
chore: Updates snapshot tests
Jul 8, 2024
905b9c5
chore: Updates testutilStyles and sets autoComplete to false by default
Jul 9, 2024
896a3ee
fix: Fixes from sign-off, including classic height bug
Jul 10, 2024
ea59a96
fix: Add check for negative or zero maxRows
Jul 11, 2024
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
82 changes: 82 additions & 0 deletions pages/prompt-input/permutations.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React from 'react';
import PromptInput, { PromptInputProps } from '~components/prompt-input';
import createPermutations from '../utils/permutations';
import PermutationsView from '../utils/permutations-view';
import ScreenshotArea from '../utils/screenshot-area';
import img from '../icon/custom-icon.png';

const permutations = createPermutations<PromptInputProps>([
{
invalid: [false, true],
warning: [false, true],
actionButtonIconName: [undefined, 'send'],
value: [
'',
'Short value',
'Long value, enough to extend beyond the input width. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
],
},
{
value: [''],
placeholder: [
'Short placeholder',
'Long placeholder, enough to extend beyond the input width. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
],
},
{
disabled: [false, true],
actionButtonIconName: [undefined, 'send'],
value: ['', 'Short value'],
},
{
value: [
'',
'Short value',
'Long value, enough to extend beyond the input width. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
],
actionButtonIconSvg: [
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" focusable="false" key="0">
<g>
<line x1="5.5" y1="12" x2="5.5" y2="15" />
<line x1="0.5" y1="15" x2="10.5" y2="15" />
<rect x="1" y="5" width="9" height="7" />
<polyline points="5 4 5 1 14 1 14 8 10 8" />
</g>
</svg>,
],
},
{
value: [
'',
'Short value',
'Long value, enough to extend beyond the input width. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
],
actionButtonIconUrl: [img],
actionButtonIconAlt: ['Letter A'],
},
]);

export default function PromptInputPermutations() {
return (
<>
<h1>PromptInput permutations</h1>
<ScreenshotArea>
<PermutationsView
permutations={permutations}
render={permutation => (
<PromptInput
ariaLabel="Prompt input field"
actionButtonAriaLabel="Action button aria label"
onChange={() => {
/*empty handler to suppress react controlled property warning*/
}}
{...permutation}
/>
)}
/>
</ScreenshotArea>
</>
);
}
43 changes: 43 additions & 0 deletions pages/prompt-input/prompt-input-integ.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useState } from 'react';
import PromptInput from '~components/prompt-input';

export default function Page() {
const [value, setValue] = useState('');
const [submitStatus, setSubmitStatus] = useState(false);
const [isKeyboardSubmittingDisabled, setDisableKeyboardSubmitting] = useState(false);

return (
<div id="test">
<h1>Prompt input submit check</h1>
{submitStatus ? <div id="submit-success">Submitted</div> : null}
<form
onSubmit={event => {
console.log('submitted');
event.preventDefault();
setSubmitStatus(true);
}}
>
<PromptInput
ariaLabel="test prompt input"
actionButtonIconName="send"
actionButtonAriaLabel="Send"
value={value}
onChange={event => setValue(event.detail.value)}
onAction={() => window.alert('Sent message!')}
onKeyDown={event => {
if (isKeyboardSubmittingDisabled) {
console.log('prevent!');
event.preventDefault();
event.stopPropagation();
}
}}
/>
<button id="disable-form-submitting" onClick={() => setDisableKeyboardSubmitting(true)} type="button">
Disable keyboard form submitting
</button>
</form>
</div>
);
}
103 changes: 103 additions & 0 deletions pages/prompt-input/simple.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useState, useContext, useEffect } from 'react';
import ColumnLayout from '~components/column-layout';
import FormField from '~components/form-field';
import PromptInput from '~components/prompt-input';
import SpaceBetween from '~components/space-between';
import Checkbox from '~components/checkbox';
import AppContext, { AppContextType } from '../app/app-context';

const MAX_CHARS = 200;

type DemoContext = React.Context<
AppContextType<{
isDisabled: boolean;
isReadOnly: boolean;
isInvalid: boolean;
hasWarning: boolean;
hasText: boolean;
}>
>;

const placeholderText =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';

export default function PromptInputPage() {
const [textareaValue, setTextareaValue] = useState('');
const { urlParams, setUrlParams } = useContext(AppContext as DemoContext);

const { isDisabled, isReadOnly, isInvalid, hasWarning, hasText } = urlParams;

useEffect(() => {
if (hasText) {
setTextareaValue(placeholderText);
}
}, [hasText]);

useEffect(() => {
if (textareaValue !== placeholderText) {
setUrlParams({ hasText: false });
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [textareaValue]);

const ref = React.createRef<HTMLTextAreaElement>();

return (
<div style={{ padding: 10 }}>
<h1>PromptInput demo</h1>
<SpaceBetween size="xl">
<FormField label="Settings">
<Checkbox checked={isDisabled} onChange={() => setUrlParams({ isDisabled: !isDisabled })}>
Disabled
</Checkbox>
<Checkbox checked={isReadOnly} onChange={() => setUrlParams({ isReadOnly: !isReadOnly })}>
Read-only
</Checkbox>
<Checkbox checked={isInvalid} onChange={() => setUrlParams({ isInvalid: !isInvalid })}>
Invalid
</Checkbox>
<Checkbox checked={hasWarning} onChange={() => setUrlParams({ hasWarning: !hasWarning })}>
Warning
</Checkbox>
</FormField>
<button id="placeholder-text-button" onClick={() => setUrlParams({ hasText: true })}>
Fill with placeholder text
</button>

<button onClick={() => ref.current?.focus()}>Focus component</button>
<button onClick={() => ref.current?.select()}>Select all text</button>

<ColumnLayout columns={2}>
<FormField
errorText={textareaValue.length > MAX_CHARS && 'The query has too many characters.'}
constraintText={
<>
This service is subject to some policy. Character count: {textareaValue.length}/{MAX_CHARS}
</>
}
label={<span>User prompt</span>}
i18nStrings={{ errorIconAriaLabel: 'Error' }}
>
<PromptInput
actionButtonIconName="send"
actionButtonAriaLabel="Submit prompt"
value={textareaValue}
onChange={(event: any) => setTextareaValue(event.detail.value)}
onAction={event => window.alert(`Submitted the following: ${event.detail.value}`)}
placeholder="Ask a question"
maxRows={4}
disabled={isDisabled}
readOnly={isReadOnly}
invalid={isInvalid || textareaValue.length > MAX_CHARS}
warning={hasWarning}
ref={ref}
/>
</FormField>
<div />
</ColumnLayout>
</SpaceBetween>
</div>
);
}
Loading
Loading