diff --git a/web/components/button.react.js b/web/components/button.react.js --- a/web/components/button.react.js +++ b/web/components/button.react.js @@ -12,7 +12,7 @@ | 'danger' | 'round'; -type Props = { +export type ButtonProps = { +onClick: (event: SyntheticEvent) => mixed, +children: React.Node, +variant?: ButtonVariant, @@ -21,7 +21,7 @@ +className?: string, }; -function Button(props: Props): React.Node { +function Button(props: ButtonProps): React.Node { const { onClick, children, diff --git a/web/modals/threads/settings/submit-section.css b/web/modals/threads/settings/submit-section.css new file mode 100644 --- /dev/null +++ b/web/modals/threads/settings/submit-section.css @@ -0,0 +1,22 @@ +.container { + height: 100%; + width: 100%; + display: flex; + flex-direction: column; +} + +.error { + text-align: center; + font-size: 16px; + color: var(--error); + font-style: italic; + + margin-top: auto; + padding: 5px; +} + +.button { + width: 100%; + align-self: flex-end; + min-height: 45px; +} diff --git a/web/modals/threads/settings/submit-section.react.js b/web/modals/threads/settings/submit-section.react.js new file mode 100644 --- /dev/null +++ b/web/modals/threads/settings/submit-section.react.js @@ -0,0 +1,46 @@ +// @flow + +import classnames from 'classnames'; +import * as React from 'react'; + +import type { ButtonProps } from '../../../components/button.react'; +import Button from '../../../components/button.react'; +import css from './submit-section.css'; + +type Props = { + ...ButtonProps, + +errorMessage?: ?string, + +containerClassName?: string, +}; + +function SubmitSection(props: Props): React.Node { + const { + children, + containerClassName = '', + errorMessage, + onClick, + variant, + disabled = false, + className = '', + } = props; + + const containerStyle = classnames(css.container, containerClassName); + const buttonStyle = classnames(css.button, className); + + return ( +
+
{errorMessage}
+ +
+ ); +} + +export default SubmitSection; diff --git a/web/modals/threads/settings/thread-settings-delete-tab.css b/web/modals/threads/settings/thread-settings-delete-tab.css --- a/web/modals/threads/settings/thread-settings-delete-tab.css +++ b/web/modals/threads/settings/thread-settings-delete-tab.css @@ -19,13 +19,15 @@ margin-bottom: 12px; } +form.container { + display: flex; + flex-direction: column; + flex: 1; +} + .deletion_warning { font-weight: var(--bold); color: var(--fg); font-size: var(--s-font-14); margin-bottom: 16px; } - -.delete_button { - width: 100%; -} diff --git a/web/modals/threads/settings/thread-settings-delete-tab.react.js b/web/modals/threads/settings/thread-settings-delete-tab.react.js --- a/web/modals/threads/settings/thread-settings-delete-tab.react.js +++ b/web/modals/threads/settings/thread-settings-delete-tab.react.js @@ -13,16 +13,17 @@ useServerCall, } from 'lib/utils/action-utils'; -import Button from '../../../components/button.react'; import SWMansionIcon from '../../../SWMansionIcon.react'; import Input from '../../input.react'; import { useModalContext } from '../../modal-provider.react'; +import SubmitSection from './submit-section.react'; import css from './thread-settings-delete-tab.css'; type ThreadSettingsDeleteTabProps = { +threadSettingsOperationInProgress: boolean, +threadInfo: ThreadInfo, - +setErrorMessage: SetState, + +setErrorMessage: SetState, + +errorMessage?: ?string, }; function ThreadSettingsDeleteTab( @@ -32,6 +33,7 @@ threadSettingsOperationInProgress, threadInfo, setErrorMessage, + errorMessage, } = props; const modalContext = useModalContext(); @@ -83,7 +85,7 @@ ); return ( -
+

@@ -107,16 +109,16 @@ />

- +
); } diff --git a/web/modals/threads/settings/thread-settings-general-tab.css b/web/modals/threads/settings/thread-settings-general-tab.css --- a/web/modals/threads/settings/thread-settings-general-tab.css +++ b/web/modals/threads/settings/thread-settings-general-tab.css @@ -27,7 +27,8 @@ margin-bottom: 12px; } -.save_button { - width: 100%; - min-height: 46px; +form.container { + display: flex; + flex-direction: column; + flex: 1; } diff --git a/web/modals/threads/settings/thread-settings-general-tab.react.js b/web/modals/threads/settings/thread-settings-general-tab.react.js --- a/web/modals/threads/settings/thread-settings-general-tab.react.js +++ b/web/modals/threads/settings/thread-settings-general-tab.react.js @@ -20,10 +20,10 @@ } from 'lib/utils/action-utils'; import { firstLine } from 'lib/utils/string-utils'; -import Button from '../../../components/button.react'; import LoadingIndicator from '../../../loading-indicator.react'; import Input from '../../input.react'; import ColorSelector from '../color-selector.react'; +import SubmitSection from './submit-section.react'; import css from './thread-settings-general-tab.css'; type ThreadSettingsGeneralTabProps = { @@ -32,7 +32,8 @@ +threadNamePlaceholder: string, +queuedChanges: ThreadChanges, +setQueuedChanges: SetState, - +setErrorMessage: SetState, + +setErrorMessage: SetState, + +errorMessage?: ?string, }; function ThreadSettingsGeneralTab( props: ThreadSettingsGeneralTabProps, @@ -44,6 +45,7 @@ queuedChanges, setQueuedChanges, setErrorMessage, + errorMessage, } = props; const dispatchActionPromise = useDispatchActionPromise(); @@ -145,7 +147,7 @@ }, [threadSettingsOperationInProgress]); return ( -
+
Chat name
@@ -182,14 +184,13 @@ />
- +
); } diff --git a/web/modals/threads/settings/thread-settings-modal.css b/web/modals/threads/settings/thread-settings-modal.css --- a/web/modals/threads/settings/thread-settings-modal.css +++ b/web/modals/threads/settings/thread-settings-modal.css @@ -2,18 +2,24 @@ display: flex; flex-direction: column; width: 383px; - height: 539px; + height: 560px; overflow: hidden; } div.tab_body { padding: 20px; overflow: auto; + flex: 1; + display: flex; + flex-direction: column; } div.modal_form_error { display: flex; + align-items: flex-end; justify-content: center; - padding-top: 8px; - font-size: 16px; - color: red; + font-size: var(--s-font-16); + color: var(--error); font-style: italic; + min-height: 26px; + flex: 1; + padding: 5px; } diff --git a/web/modals/threads/settings/thread-settings-modal.react.js b/web/modals/threads/settings/thread-settings-modal.react.js --- a/web/modals/threads/settings/thread-settings-modal.react.js +++ b/web/modals/threads/settings/thread-settings-modal.react.js @@ -59,7 +59,7 @@ state => threadInfoSelector(state)[props.threadID], ); const modalContext = useModalContext(); - const [errorMessage, setErrorMessage] = React.useState(''); + const [errorMessage, setErrorMessage] = React.useState(''); const [currentTabType, setCurrentTabType] = React.useState( 'general', ); @@ -144,8 +144,8 @@ queuedChanges={queuedChanges} setQueuedChanges={setQueuedChanges} setErrorMessage={setErrorMessage} + errorMessage={errorMessage} /> -
{errorMessage}
, ]; @@ -169,8 +169,8 @@ queuedChanges={queuedChanges} setQueuedChanges={setQueuedChanges} setErrorMessage={setErrorMessage} + errorMessage={errorMessage} /> -
{errorMessage}
, ); @@ -200,8 +200,8 @@ threadSettingsOperationInProgress={changeInProgress} threadInfo={threadInfo} setErrorMessage={setErrorMessage} + errorMessage={errorMessage} /> -
{errorMessage}
, ); diff --git a/web/modals/threads/settings/thread-settings-privacy-tab.css b/web/modals/threads/settings/thread-settings-privacy-tab.css --- a/web/modals/threads/settings/thread-settings-privacy-tab.css +++ b/web/modals/threads/settings/thread-settings-privacy-tab.css @@ -8,6 +8,8 @@ padding: 12px 0; } -.save_button { - width: 100%; +form.container { + display: flex; + flex-direction: column; + flex: 1; } diff --git a/web/modals/threads/settings/thread-settings-privacy-tab.react.js b/web/modals/threads/settings/thread-settings-privacy-tab.react.js --- a/web/modals/threads/settings/thread-settings-privacy-tab.react.js +++ b/web/modals/threads/settings/thread-settings-privacy-tab.react.js @@ -18,10 +18,10 @@ useServerCall, } from 'lib/utils/action-utils'; -import Button from '../../../components/button.react'; import EnumSettingsOption from '../../../components/enum-settings-option.react'; import SWMansionIcon from '../../../SWMansionIcon.react'; import { useModalContext } from '../../modal-provider.react'; +import SubmitSection from './submit-section.react'; import css from './thread-settings-privacy-tab.css'; const { COMMUNITY_OPEN_SUBTHREAD, COMMUNITY_SECRET_SUBTHREAD } = threadTypes; @@ -47,7 +47,8 @@ +threadInfo: ThreadInfo, +queuedChanges: ThreadChanges, +setQueuedChanges: SetState, - +setErrorMessage: SetState, + +setErrorMessage: SetState, + +errorMessage?: ?string, }; function ThreadSettingsPrivacyTab( props: ThreadSettingsPrivacyTabProps, @@ -58,6 +59,7 @@ queuedChanges, setQueuedChanges, setErrorMessage, + errorMessage, } = props; const modalContext = useModalContext(); @@ -138,7 +140,7 @@ ); return ( -
+
Chat type
- +
); } diff --git a/web/modals/threads/settings/thread-settings-relationship-button.react.js b/web/modals/threads/settings/thread-settings-relationship-button.react.js --- a/web/modals/threads/settings/thread-settings-relationship-button.react.js +++ b/web/modals/threads/settings/thread-settings-relationship-button.react.js @@ -40,7 +40,7 @@ type ButtonProps = { +relationshipButton: RelationshipButton, +otherUserInfo: UserInfo, - +setErrorMessage?: SetState, + +setErrorMessage?: SetState, }; function ThreadSettingsRelationshipButton(props: ButtonProps): React.Node { diff --git a/web/modals/threads/settings/thread-settings-relationship-tab.react.js b/web/modals/threads/settings/thread-settings-relationship-tab.react.js --- a/web/modals/threads/settings/thread-settings-relationship-tab.react.js +++ b/web/modals/threads/settings/thread-settings-relationship-tab.react.js @@ -10,7 +10,7 @@ import css from './thread-settings-relationship-tab.css'; type Props = { - +setErrorMessage: SetState, + +setErrorMessage: SetState, +relationshipButtons: $ReadOnlyArray, +otherUserInfo: UserInfo, };