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: File token group [internal] #2950

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
3 changes: 2 additions & 1 deletion pages/file-upload/permutations.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const permutations = createPermutations<Omit<FileUploadProps, 'dismissAriaLabel'
value: [
[
new File([new Blob(['demo content 1'])], 'demo file 1', { type: 'image/*' }),
new File([new Blob(['demo content 2'])], 'demo file 2', { type: 'image/*' }),
new File([new Blob(['demo content 2'])], 'demo file 2 with long file name', { type: 'image/*' }),
],
],
showFileSize: [true],
Expand All @@ -37,6 +37,7 @@ const permutations = createPermutations<Omit<FileUploadProps, 'dismissAriaLabel'
constraintText: ['File size must not exceed 1 MB'],
fileErrors: [undefined, ['File size is above 1 MB', 'File size is above 1 MB']],
fileWarnings: [undefined, ['File type is image', 'File type is image']],
fileTokenAlignment: ['vertical', 'horizontal'],
},
]);

Expand Down
6 changes: 6 additions & 0 deletions pages/file-upload/scenario-standalone.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { validateContractFiles } from './validations';
export default function FileUploadScenarioStandalone() {
const contractsRef = useRef<FileUploadProps.Ref>(null);
const [acceptMultiple, setAcceptMultiple] = useState(true);
const [verticalAlignment, setVerticalAlignment] = useState(true);
const formState = useContractFilesForm();

const contractsValidationErrors = validateContractFiles(formState.files);
Expand Down Expand Up @@ -40,11 +41,16 @@ export default function FileUploadScenarioStandalone() {
Accept multiple files
</Checkbox>

<Checkbox checked={verticalAlignment} onChange={event => setVerticalAlignment(event.detail.checked)}>
Vertical alignment
</Checkbox>

<FormField
label={acceptMultiple ? 'Contracts' : 'Contract'}
description={acceptMultiple ? 'Upload your contract with all amendments' : 'Upload your contract'}
>
<FileUpload
fileTokenAlignment={verticalAlignment ? 'vertical' : 'horizontal'}
ref={contractsRef}
multiple={acceptMultiple}
tokenLimit={3}
Expand Down
14 changes: 14 additions & 0 deletions src/__tests__/__snapshots__/documenter.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7453,6 +7453,20 @@ is provided by its parent form field component.
"optional": true,
"type": "ReadonlyArray<null | string>",
},
{
"description": "Alignment of the file tokens. Defaults to "vertical".",
"inlineType": {
"name": "FileUploadProps.FileTokenAlignment",
"type": "union",
"values": [
"vertical",
"horizontal",
],
},
"name": "fileTokenAlignment",
"optional": true,
"type": "string",
},
{
"description": "An array of file warnings corresponding to the files in the \`value\`.",
"name": "fileWarnings",
Expand Down
10 changes: 6 additions & 4 deletions src/__tests__/__snapshots__/test-utils-selectors.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -250,10 +250,6 @@ exports[`test-utils selectors 1`] = `
"awsui_root_gwq0h",
],
"file-upload": [
"awsui_file-option-last-modified_ezgb4",
"awsui_file-option-name_ezgb4",
"awsui_file-option-size_ezgb4",
"awsui_file-option-thumbnail-image_ezgb4",
"awsui_hints_1ubbm",
"awsui_root_1ubbm",
],
Expand Down Expand Up @@ -339,6 +335,11 @@ exports[`test-utils selectors 1`] = `
"awsui_dropdown_qwoo0",
"awsui_file-input-button_181f9",
"awsui_file-input_181f9",
"awsui_file-option-last-modified_ofwwb",
"awsui_file-option-name_ofwwb",
"awsui_file-option-size_ofwwb",
"awsui_file-option-thumbnail_ofwwb",
"awsui_file-token_ofwwb",
"awsui_filter-container_z5mul",
"awsui_filtering-match-highlight_1p2cx",
"awsui_handle_sdha6",
Expand All @@ -365,6 +366,7 @@ exports[`test-utils selectors 1`] = `
"awsui_root_1qprf",
"awsui_root_1t44z",
"awsui_root_1tk3k",
"awsui_root_9f1dn",
"awsui_root_qwoo0",
"awsui_root_vrgzu",
"awsui_selectable-item_15o6u",
Expand Down
47 changes: 0 additions & 47 deletions src/file-upload/file-option/index.tsx

This file was deleted.

34 changes: 0 additions & 34 deletions src/file-upload/file-option/styles.scss

This file was deleted.

6 changes: 6 additions & 0 deletions src/file-upload/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ export interface FileUploadProps extends BaseComponentProps, FormFieldCommonVali
* An array of file warnings corresponding to the files in the `value`.
*/
fileWarnings?: ReadonlyArray<null | string>;
/**
* Alignment of the file tokens. Defaults to "vertical".
*/
fileTokenAlignment?: FileUploadProps.FileTokenAlignment;
/**
* An object containing all the localized strings required by the component:
* * `uploadButtonText` (function): A function to render the text of the file upload button. It takes `multiple` attribute to define plurality.
Expand All @@ -89,6 +93,8 @@ export namespace FileUploadProps {
file: File;
}

export type FileTokenAlignment = 'vertical' | 'horizontal';

export interface I18nStrings {
uploadButtonText: (multiple: boolean) => string;
dropzoneText: (multiple: boolean) => string;
Expand Down
70 changes: 28 additions & 42 deletions src/file-upload/internal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import { ConstraintText, FormFieldError, FormFieldWarning } from '../form-field/
import { getBaseProps } from '../internal/base-component';
import InternalFileDropzone, { useFilesDragging } from '../internal/components/file-dropzone';
import InternalFileInput from '../internal/components/file-input';
import TokenList from '../internal/components/token-list';
import InternalFileTokenGroup from '../internal/components/file-token-group';
import InternalFileToken from '../internal/components/file-token-group/file-token';
import { fireNonCancelableEvent } from '../internal/events';
import checkControlled from '../internal/hooks/check-controlled';
import { InternalBaseComponentProps } from '../internal/hooks/use-base-component';
Expand All @@ -22,8 +23,6 @@ import { useMergeRefs } from '../internal/hooks/use-merge-refs';
import { useUniqueId } from '../internal/hooks/use-unique-id';
import { joinStrings } from '../internal/utils/strings';
import InternalSpaceBetween from '../space-between/internal';
import { Token } from '../token-group/token';
import { FileOption } from './file-option';
import { FileUploadProps } from './interfaces';

import fileInputStyles from '../internal/components/file-input/styles.css.js';
Expand Down Expand Up @@ -52,6 +51,7 @@ function InternalFileUpload(
warningText,
fileErrors,
fileWarnings,
fileTokenAlignment = 'vertical',
...restProps
}: InternalFileUploadProps,
externalRef: ForwardedRef<ButtonProps.Ref>
Expand Down Expand Up @@ -165,48 +165,34 @@ function InternalFileUpload(
</InternalBox>

{!multiple && value.length > 0 ? (
<InternalBox>
<Token
ariaLabel={value[0].name}
dismissLabel={i18nStrings.removeFileAriaLabel(0)}
onDismiss={() => onFileRemove(0)}
errorText={fileErrors?.[0]}
warningText={fileWarnings?.[0]}
errorIconAriaLabel={i18nStrings.errorIconAriaLabel}
warningIconAriaLabel={i18nStrings.warningIconAriaLabel}
data-index={0}
>
<FileOption file={value[0]} metadata={metadata} i18nStrings={i18nStrings} />
</Token>
</InternalBox>
<InternalFileToken
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This component is not going public, right? I wonder if we then should change the implementation here so that the single-file file upload would still render a list, yet with a single item. That is to be consistent with custom implementations using FileInput + FileTokenGroup.

file={value[0]}
showFileLastModified={metadata.showFileLastModified}
showFileSize={metadata.showFileSize}
showFileThumbnail={metadata.showFileThumbnail}
errorText={fileErrors?.[0]}
warningText={fileWarnings?.[0]}
onDismiss={() => onFileRemove(0)}
i18nStrings={i18nStrings}
index={0}
/>
) : null}

{multiple && value.length > 0 ? (
<InternalBox>
<TokenList
alignment="vertical"
items={value}
renderItem={(file, fileIndex) => (
<Token
ariaLabel={file.name}
dismissLabel={i18nStrings.removeFileAriaLabel(fileIndex)}
onDismiss={() => onFileRemove(fileIndex)}
errorText={fileErrors?.[fileIndex]}
warningText={fileWarnings?.[fileIndex]}
errorIconAriaLabel={i18nStrings.errorIconAriaLabel}
warningIconAriaLabel={i18nStrings.warningIconAriaLabel}
data-index={fileIndex}
>
<FileOption file={file} metadata={metadata} i18nStrings={i18nStrings} />
</Token>
)}
limit={tokenLimit}
i18nStrings={{
limitShowFewer: i18nStrings.limitShowFewer,
limitShowMore: i18nStrings.limitShowMore,
}}
/>
</InternalBox>
<InternalFileTokenGroup
limit={tokenLimit}
alignment={fileTokenAlignment}
items={value.map((file, fileIndex) => ({
file,
errorText: fileErrors?.[fileIndex],
warningText: fileWarnings?.[fileIndex],
}))}
showFileLastModified={metadata.showFileLastModified}
showFileSize={metadata.showFileSize}
showFileThumbnail={metadata.showFileThumbnail}
i18nStrings={i18nStrings}
onDismiss={event => onFileRemove(event.detail.fileIndex)}
/>
) : null}
</InternalSpaceBetween>
);
Expand Down
Loading
Loading