diff --git a/src/elements/common/modal.scss b/src/elements/common/modal.scss
index 2af639a7bd..8c922c8b91 100644
--- a/src/elements/common/modal.scss
+++ b/src/elements/common/modal.scss
@@ -44,12 +44,19 @@
background-color: $darker-black;
}
+.be-modal-rename .be-modal-dialog-content,
.be-modal-share .be-modal-dialog-content,
.be-modal-delete .be-modal-dialog-content {
padding: 0;
border-radius: tokens.$radius-4;
}
+.be-modal-rename .be-modal-dialog-content {
+ input {
+ width: 100%;
+ }
+}
+
.be-modal-dialog-content {
@extend .be-modal-wrapper-content;
diff --git a/src/elements/content-explorer/RenameDialog.js b/src/elements/content-explorer/RenameDialog.js.flow
similarity index 60%
rename from src/elements/content-explorer/RenameDialog.js
rename to src/elements/content-explorer/RenameDialog.js.flow
index 1ae780c58c..4bf89189e7 100644
--- a/src/elements/content-explorer/RenameDialog.js
+++ b/src/elements/content-explorer/RenameDialog.js.flow
@@ -1,16 +1,8 @@
-/**
- * @flow
- * @file Content Explorer Rename Dialog
- * @author Box
- */
-
import * as React from 'react';
import Modal from 'react-modal';
-import { injectIntl, FormattedMessage } from 'react-intl';
-import type { IntlShape } from 'react-intl';
-import PrimaryButton from '../../components/primary-button/PrimaryButton';
-import Button from '../../components/button/Button';
-import messages from '../common/messages';
+import { FormattedMessage, useIntl } from 'react-intl';
+import { Modal as BlueprintModal, Text } from '@box/blueprint-web';
+
import {
CLASS_MODAL_CONTENT,
CLASS_MODAL_OVERLAY,
@@ -20,30 +12,30 @@ import {
} from '../../constants';
import type { BoxItem } from '../../common/types/core';
+import messages from '../common/messages';
+
type Props = {
appElement: HTMLElement,
errorCode: string,
- intl: IntlShape,
isLoading: boolean,
isOpen: boolean,
item: BoxItem,
- onCancel: Function,
- onRename: Function,
- parentElement: HTMLElement,
+ onCancel: any,
+ onRename: any,
+ parentElement: HTMLElement
};
-/* eslint-disable jsx-a11y/label-has-for */
const RenameDialog = ({
+ appElement,
+ errorCode,
isOpen,
- onRename,
- onCancel,
- item,
isLoading,
- errorCode,
+ item,
+ onCancel,
+ onRename,
parentElement,
- appElement,
- intl,
}: Props) => {
+ const { formatMessage } = useIntl();
let textInput = null;
let error;
@@ -54,7 +46,7 @@ const RenameDialog = ({
/**
* Appends the extension and calls rename function
*/
- const rename = () => {
+ const handleRename = () => {
if (textInput && textInput.value) {
if (textInput.value === nameWithoutExt) {
onCancel();
@@ -81,7 +73,7 @@ const RenameDialog = ({
const onKeyDown = ({ key }) => {
switch (key) {
case 'Enter':
- rename();
+ handleRename();
break;
default:
break;
@@ -104,32 +96,41 @@ const RenameDialog = ({
parentElement}
portalClassName={`${CLASS_MODAL} be-modal-rename`}
>
-
-
+
+
+
+ {formatMessage(messages.cancel)}
+
+
+ {formatMessage(messages.rename)}
+
+
);
};
-export default injectIntl(RenameDialog);
+export default RenameDialog;
diff --git a/src/elements/content-explorer/RenameDialog.tsx b/src/elements/content-explorer/RenameDialog.tsx
new file mode 100644
index 0000000000..575bfbb1e1
--- /dev/null
+++ b/src/elements/content-explorer/RenameDialog.tsx
@@ -0,0 +1,136 @@
+import * as React from 'react';
+import Modal from 'react-modal';
+import { FormattedMessage, useIntl } from 'react-intl';
+import { Modal as BlueprintModal, Text } from '@box/blueprint-web';
+
+import {
+ CLASS_MODAL_CONTENT,
+ CLASS_MODAL_OVERLAY,
+ CLASS_MODAL,
+ ERROR_CODE_ITEM_NAME_TOO_LONG,
+ ERROR_CODE_ITEM_NAME_IN_USE,
+} from '../../constants';
+import type { BoxItem } from '../../common/types/core';
+
+import messages from '../common/messages';
+
+export interface RenameDialogProps {
+ appElement: HTMLElement;
+ errorCode: string;
+ isLoading: boolean;
+ isOpen: boolean;
+ item: BoxItem;
+ onCancel: () => void;
+ onRename: (value: string, extension: string) => void;
+ parentElement: HTMLElement;
+}
+
+const RenameDialog = ({
+ appElement,
+ errorCode,
+ isOpen,
+ isLoading,
+ item,
+ onCancel,
+ onRename,
+ parentElement,
+}: RenameDialogProps) => {
+ const { formatMessage } = useIntl();
+ let textInput = null;
+ let error;
+
+ const { name = '', extension } = item;
+ const ext = extension ? `.${extension}` : '';
+ const nameWithoutExt = extension ? name.replace(ext, '') : name;
+
+ /**
+ * Appends the extension and calls rename function
+ */
+ const handleRename = () => {
+ if (textInput && textInput.value) {
+ if (textInput.value === nameWithoutExt) {
+ onCancel();
+ } else {
+ onRename(textInput.value, ext);
+ }
+ }
+ };
+
+ /**
+ * Grabs reference to the input element
+ */
+ const ref = input => {
+ textInput = input;
+ if (textInput instanceof HTMLInputElement) {
+ textInput.focus();
+ textInput.select();
+ }
+ };
+
+ /**
+ * Handles enter key down
+ */
+ const onKeyDown = ({ key }) => {
+ switch (key) {
+ case 'Enter':
+ handleRename();
+ break;
+ default:
+ break;
+ }
+ };
+
+ switch (errorCode) {
+ case ERROR_CODE_ITEM_NAME_IN_USE:
+ error = messages.renameDialogErrorInUse;
+ break;
+ case ERROR_CODE_ITEM_NAME_TOO_LONG:
+ error = messages.renameDialogErrorTooLong;
+ break;
+ default:
+ error = errorCode ? messages.renameDialogErrorInvalid : null;
+ break;
+ }
+
+ return (
+ parentElement}
+ portalClassName={`${CLASS_MODAL} be-modal-rename`}
+ >
+
+
+ {error && (
+
+
+
+ )}
+
+
+
+
+
+
+
+
+ {formatMessage(messages.cancel)}
+
+
+ {formatMessage(messages.rename)}
+
+
+
+ );
+};
+
+export default RenameDialog;
diff --git a/src/elements/content-explorer/stories/RenameDialog.stories.tsx b/src/elements/content-explorer/stories/RenameDialog.stories.tsx
new file mode 100644
index 0000000000..b51bd41754
--- /dev/null
+++ b/src/elements/content-explorer/stories/RenameDialog.stories.tsx
@@ -0,0 +1,49 @@
+import * as React from 'react';
+import { useArgs } from '@storybook/preview-api';
+import { Button } from '@box/blueprint-web';
+
+import { addRootElement } from '../../../utils/storybook';
+
+import RenameDialog, { RenameDialogProps } from '../RenameDialog';
+
+export const renameDialog = {
+ render: (args: RenameDialogProps) => {
+ // eslint-disable-next-line react-hooks/rules-of-hooks
+ const [, setArgs] = useArgs();
+
+ const handleOpenModal = () => setArgs({ isOpen: true });
+
+ const handleCloseModal = () => {
+ setArgs({ isOpen: false });
+ };
+
+ const { appElement, rootElement } = addRootElement();
+
+ return (
+
+
+
+
+ );
+ },
+};
+
+export default {
+ title: 'Elements/ContentExplorer',
+ component: RenameDialog,
+ args: {
+ isLoading: false,
+ isOpen: false,
+ },
+};
diff --git a/src/elements/content-explorer/stories/tests/RenameDialog-visual.stories.js b/src/elements/content-explorer/stories/tests/RenameDialog-visual.stories.tsx
similarity index 79%
rename from src/elements/content-explorer/stories/tests/RenameDialog-visual.stories.js
rename to src/elements/content-explorer/stories/tests/RenameDialog-visual.stories.tsx
index 06721da6ca..8ef71df648 100644
--- a/src/elements/content-explorer/stories/tests/RenameDialog-visual.stories.js
+++ b/src/elements/content-explorer/stories/tests/RenameDialog-visual.stories.tsx
@@ -2,7 +2,7 @@ import * as React from 'react';
import { addRootElement, defaultVisualConfig } from '../../../../utils/storybook';
-import RenameDialog from '../../RenameDialog';
+import RenameDialog, { RenameDialogProps } from '../../RenameDialog';
import {
ERROR_CODE_ITEM_NAME_IN_USE,
ERROR_CODE_ITEM_NAME_INVALID,
@@ -22,25 +22,34 @@ const itemWithLongName = {
};
export const renameDialogNotLoading = {
- render: () => {
+ render: (args: RenameDialogProps) => {
const { appElement, rootElement } = addRootElement();
return (
-
+
);
},
};
export const renameDialogIsLoading = {
- render: () => {
+ render: (args: RenameDialogProps) => {
const { appElement, rootElement } = addRootElement();
- return ;
+ return (
+
+ );
},
};
export const renameDialogNameInvalidError = {
- render: () => {
+ render: (args: RenameDialogProps) => {
const { appElement, rootElement } = addRootElement();
return (
@@ -51,13 +60,14 @@ export const renameDialogNameInvalidError = {
isOpen
item={item}
parentElement={rootElement}
+ {...args}
/>
);
},
};
export const renameDialogNameInUseError = {
- render: () => {
+ render: (args: RenameDialogProps) => {
const { appElement, rootElement } = addRootElement();
return (
@@ -68,13 +78,14 @@ export const renameDialogNameInUseError = {
isOpen
item={item}
parentElement={rootElement}
+ {...args}
/>
);
},
};
export const renameDialogNameTooLongError = {
- render: () => {
+ render: (args: RenameDialogProps) => {
const { appElement, rootElement } = addRootElement();
return (
@@ -85,6 +96,7 @@ export const renameDialogNameTooLongError = {
isOpen
item={itemWithLongName}
parentElement={rootElement}
+ {...args}
/>
);
},