soumaeda 2 лет назад
Родитель
Сommit
9281e98513
64 измененных файлов с 291 добавлено и 189 удалено
  1. 1 1
      apps/app/src/components/Admin/AuditLog/AuditLogSettings.tsx
  2. 5 1
      apps/app/src/components/Admin/Common/Accordion.jsx
  3. 21 17
      apps/app/src/components/Admin/Customize/CustomizeLayoutSetting.tsx
  4. 21 17
      apps/app/src/components/Admin/Customize/CustomizeSidebarSetting.tsx
  5. 1 1
      apps/app/src/components/Admin/Customize/ThemeColorBox.tsx
  6. 12 8
      apps/app/src/components/Admin/ElasticsearchManagement/StatusTable.jsx
  7. 1 1
      apps/app/src/components/Admin/ImportData/GrowiArchive/ImportCollectionItem.jsx
  8. 6 6
      apps/app/src/components/Admin/Notification/GlobalNotificationList.jsx
  9. 6 6
      apps/app/src/components/Admin/Notification/ManageGlobalNotification.tsx
  10. 3 3
      apps/app/src/components/Admin/Notification/NotificationSetting.jsx
  11. 1 1
      apps/app/src/components/Admin/Security/GitHubSecuritySettingContents.jsx
  12. 1 1
      apps/app/src/components/Admin/Security/GoogleSecuritySettingContents.jsx
  13. 1 1
      apps/app/src/components/Admin/Security/LdapSecuritySettingContents.jsx
  14. 1 1
      apps/app/src/components/Admin/Security/LocalSecuritySettingContents.jsx
  15. 1 1
      apps/app/src/components/Admin/Security/OidcSecuritySettingContents.jsx
  16. 4 2
      apps/app/src/components/Admin/Security/SamlSecuritySettingContents.jsx
  17. 1 1
      apps/app/src/components/Admin/Security/ShareLinkSetting.tsx
  18. 1 1
      apps/app/src/components/Admin/SlackIntegration/BotTypeCard.jsx
  19. 2 2
      apps/app/src/components/Admin/UserGroup/UserGroupTable.tsx
  20. 2 2
      apps/app/src/components/Admin/UserManagement.tsx
  21. 2 2
      apps/app/src/components/Admin/Users/ExternalAccountTable.tsx
  22. 9 9
      apps/app/src/components/Admin/Users/UserTable.tsx
  23. 1 1
      apps/app/src/components/Common/CountBadge.tsx
  24. 7 3
      apps/app/src/components/CreateTemplateModal.jsx
  25. 2 2
      apps/app/src/components/CustomNavigation/CustomNav.tsx
  26. 1 1
      apps/app/src/components/DescendantsPageListModal.module.scss
  27. 1 1
      apps/app/src/components/InAppNotification/InAppNotificationDropdown.tsx
  28. 1 1
      apps/app/src/components/Layout/Admin.module.scss
  29. 1 1
      apps/app/src/components/Page/RenderTagLabels.tsx
  30. 1 1
      apps/app/src/components/PageAccessoriesModal/PageAccessoriesModal.module.scss
  31. 1 1
      apps/app/src/components/PageEditor/Cheatsheet.tsx
  32. 1 1
      apps/app/src/components/PageEditor/Editor.tsx
  33. 14 26
      apps/app/src/components/PageEditor/PageEditor.tsx
  34. 2 2
      apps/app/src/components/PageEditorByHackmd.tsx
  35. 1 1
      apps/app/src/components/PageHistory/Revision.tsx
  36. 1 1
      apps/app/src/components/PagePresentationModal.module.scss
  37. 7 5
      apps/app/src/components/PagePresentationModal.tsx
  38. 2 2
      apps/app/src/components/PageSideContents.tsx
  39. 1 1
      apps/app/src/components/PageStatusAlert.tsx
  40. 1 1
      apps/app/src/components/PasswordResetExecutionForm.tsx
  41. 1 1
      apps/app/src/components/PasswordResetRequestForm.tsx
  42. 1 1
      apps/app/src/components/Sidebar/Bookmarks/BookmarkContents.tsx
  43. 1 1
      apps/app/src/components/Sidebar/PersonalDropdown.tsx
  44. 1 1
      apps/app/src/components/Sidebar/RecentChanges/RecentChangesSubstance.tsx
  45. 1 1
      apps/app/src/components/TagCloudBox.tsx
  46. 1 1
      apps/app/src/components/TagList.tsx
  47. 1 1
      apps/app/src/features/growi-plugin/client/components/Admin/PluginsExtensionPageContents/PluginCard.tsx
  48. 2 2
      apps/app/src/features/questionnaire/client/components/ProactiveQuestionnaireModal.tsx
  49. 1 1
      apps/app/src/features/questionnaire/client/components/Question.tsx
  50. 2 4
      apps/app/src/features/questionnaire/client/components/QuestionnaireToast.tsx
  51. 3 1
      apps/app/src/styles/_override-rbt.scss
  52. 2 2
      apps/app/src/styles/theme/_hsl-reboot-bootstrap-theme-colors.scss
  53. 2 2
      apps/app/src/styles/theme/_reboot-bootstrap-theme-colors.scss
  54. 2 2
      apps/app/src/styles/theme/apply-colors.scss
  55. 1 0
      packages/editor/package.json
  56. 1 1
      packages/editor/src/components/playground/Playground.tsx
  57. 60 12
      packages/editor/src/components/playground/PlaygroundController.tsx
  58. 26 0
      packages/editor/src/services/codemirror-editor/use-codemirror-editor.ts
  59. 23 0
      packages/editor/turbo.json
  60. 1 1
      packages/remark-lsx/src/client/components/Lsx.tsx
  61. 2 2
      packages/ui/src/components/Attachment.tsx
  62. 2 2
      packages/ui/src/components/PagePath/PageListMeta.tsx
  63. 0 13
      turbo.json
  64. 5 0
      yarn.lock

+ 1 - 1
apps/app/src/components/Admin/AuditLog/AuditLogSettings.tsx

@@ -37,7 +37,7 @@ export const AuditLogSettings: FC = () => {
 
       <h4 className="mt-4">
         {t('admin:audit_log_management.available_action_list')}
-        <span className="badge badge-pill badge-secondary ml-2">
+        <span className="badge rounded-pill bg-primary ml-2">
           {`${availableActions.length} / ${AllSupportedActions.length}`}
         </span>
         <a

+ 5 - 1
apps/app/src/components/Admin/Common/Accordion.jsx

@@ -1,7 +1,11 @@
 import React, { useState } from 'react';
-import { Collapse } from 'reactstrap';
+
 import PropTypes from 'prop-types';
+import { Collapse } from 'reactstrap';
+
 
+// TODO: use new accordion component
+// https://redmine.weseek.co.jp/issues/129222
 const Accordion = (props) => {
   const [isOpen, setIsOpen] = useState(props.isOpenDefault);
   return (

+ 21 - 17
apps/app/src/components/Admin/Customize/CustomizeLayoutSetting.tsx

@@ -57,25 +57,29 @@ const CustomizeLayoutSetting = (): JSX.Element => {
           <h2 className="admin-setting-header">{t('customize_settings.layout')}</h2>
 
           <div className="d-flex justify-content-around mt-5">
-            <div id="layoutOptions" className="card-deck">
-              <div
-                className={`card customize-layout-card ${!isContainerFluid ? 'border-active' : ''}`}
-                onClick={() => setIsContainerFluid(false)}
-                role="button"
-              >
-                <img src={`/images/customize-settings/default-${resolvedTheme}.svg`} />
-                <div className="card-body text-center">
-                  {t('customize_settings.layout_options.default')}
+            <div id="layoutOptions" className="row row-cols-2">
+              <div className="col">
+                <div
+                  className={`card customize-layout-card ${!isContainerFluid ? 'border-active' : ''}`}
+                  onClick={() => setIsContainerFluid(false)}
+                  role="button"
+                >
+                  <img src={`/images/customize-settings/default-${resolvedTheme}.svg`} />
+                  <div className="card-body text-center">
+                    {t('customize_settings.layout_options.default')}
+                  </div>
                 </div>
               </div>
-              <div
-                className={`card customize-layout-card ${isContainerFluid ? 'border-active' : ''}`}
-                onClick={() => setIsContainerFluid(true)}
-                role="button"
-              >
-                <img src={`/images/customize-settings/fluid-${resolvedTheme}.svg`} />
-                <div className="card-body  text-center">
-                  {t('customize_settings.layout_options.expanded')}
+              <div className="col">
+                <div
+                  className={`card customize-layout-card ${isContainerFluid ? 'border-active' : ''}`}
+                  onClick={() => setIsContainerFluid(true)}
+                  role="button"
+                >
+                  <img src={`/images/customize-settings/fluid-${resolvedTheme}.svg`} />
+                  <div className="card-body  text-center">
+                    {t('customize_settings.layout_options.expanded')}
+                  </div>
                 </div>
               </div>
             </div>

+ 21 - 17
apps/app/src/components/Admin/Customize/CustomizeSidebarSetting.tsx

@@ -42,25 +42,29 @@ const CustomizeSidebarsetting = (): JSX.Element => {
           </Card>
 
           <div className="d-flex justify-content-around mt-5">
-            <div id="layoutOptions" className="card-deck">
-              <div
-                className={`card customize-layout-card ${isSidebarDrawerMode ? 'border-active' : ''}`}
-                onClick={() => setIsSidebarDrawerMode(true)}
-                role="button"
-              >
-                <img src={drawerIconFileName} />
-                <div className="card-body text-center">
-                  Drawer Mode
+            <div id="layoutOptions" className="row row-cols-2">
+              <div className="col">
+                <div
+                  className={`card customize-layout-card ${isSidebarDrawerMode ? 'border-active' : ''}`}
+                  onClick={() => setIsSidebarDrawerMode(true)}
+                  role="button"
+                >
+                  <img src={drawerIconFileName} />
+                  <div className="card-body text-center">
+                    Drawer Mode
+                  </div>
                 </div>
               </div>
-              <div
-                className={`card customize-layout-card ${!isSidebarDrawerMode ? 'border-active' : ''}`}
-                onClick={() => setIsSidebarDrawerMode(false)}
-                role="button"
-              >
-                <img src={dockIconFileName} />
-                <div className="card-body  text-center">
-                  Dock Mode
+              <div className="col">
+                <div
+                  className={`card customize-layout-card ${!isSidebarDrawerMode ? 'border-active' : ''}`}
+                  onClick={() => setIsSidebarDrawerMode(false)}
+                  role="button"
+                >
+                  <img src={dockIconFileName} />
+                  <div className="card-body  text-center">
+                    Dock Mode
+                  </div>
                 </div>
               </div>
             </div>

+ 1 - 1
apps/app/src/components/Admin/Customize/ThemeColorBox.tsx

@@ -35,7 +35,7 @@ export const ThemeColorBox = (props: Props): JSX.Element => {
         </svg>
       </a>
       <span className="theme-option-name"><b>{ name }</b></span>
-      { !isPresetTheme && <span className="theme-option-badge badge badge-primary mt-1">Plugin</span> }
+      { !isPresetTheme && <span className="theme-option-badge badge bg-primary mt-1">Plugin</span> }
     </div>
   );
 

+ 12 - 8
apps/app/src/components/Admin/ElasticsearchManagement/StatusTable.jsx

@@ -6,7 +6,7 @@ import PropTypes from 'prop-types';
 class StatusTable extends React.PureComponent {
 
   renderPreInitializedLabel() {
-    return <span className="badge badge-pill badge-default">――</span>;
+    return <span className="badge rounded-pill bg-default">――</span>;
   }
 
   renderConnectionStatusLabels() {
@@ -17,18 +17,22 @@ class StatusTable extends React.PureComponent {
     } = this.props;
 
     const errorOccuredLabel = isErrorOccuredOnSearchService
-      ? <span className="badge badge-pill badge-danger ml-2">{ t('full_text_search_management.connection_status_label_erroroccured') }</span>
+      ? <span className="badge rounded-pill bg-danger ml-2">{ t('full_text_search_management.connection_status_label_erroroccured') }</span>
       : null;
 
     let connectionStatusLabel = null;
     if (!isConfigured) {
-      connectionStatusLabel = <span className="badge badge-pill badge-default">{ t('full_text_search_management.connection_status_label_unconfigured') }</span>;
+      connectionStatusLabel = (
+        <span className="badge rounded-pill bg-default">
+          { t('full_text_search_management.connection_status_label_unconfigured') }
+        </span>
+      );
     }
     else {
       connectionStatusLabel = isConnected
         // eslint-disable-next-line max-len
-        ? <span data-testid="connection-status-badge-connected" className="badge badge-pill badge-success">{ t('full_text_search_management.connection_status_label_connected') }</span>
-        : <span className="badge badge-pill badge-danger">{ t('full_text_search_management.connection_status_label_disconnected') }</span>;
+        ? <span data-testid="connection-status-badge-connected" className="badge rounded-pill bg-success">{ t('full_text_search_management.connection_status_label_connected') }</span>
+        : <span className="badge rounded-pill bg-danger">{ t('full_text_search_management.connection_status_label_disconnected') }</span>;
     }
 
     return (
@@ -42,8 +46,8 @@ class StatusTable extends React.PureComponent {
     const { t, isNormalized } = this.props;
 
     return isNormalized
-      ? <span className="badge badge-pill badge-info">{ t('full_text_search_management.indices_status_label_normalized') }</span>
-      : <span className="badge badge-pill badge-warning">{ t('full_text_search_management.indices_status_label_unnormalized') }</span>;
+      ? <span className="badge rounded-pill bg-info">{ t('full_text_search_management.indices_status_label_normalized') }</span>
+      : <span className="badge rounded-pill bg-warning text-dark">{ t('full_text_search_management.indices_status_label_unnormalized') }</span>;
   }
 
   renderIndexInfoPanel(indexName, body = {}, aliases = []) {
@@ -51,7 +55,7 @@ class StatusTable extends React.PureComponent {
 
     const aliasLabels = aliases.map((aliasName) => {
       return (
-        <span key={`badge-${indexName}-${aliasName}`} className="badge badge-pill badge-primary mr-2">
+        <span key={`badge-${indexName}-${aliasName}`} className="badge rounded-pill bg-primary mr-2">
           <i className="icon-tag"></i> {aliasName}
         </span>
       );

+ 1 - 1
apps/app/src/components/Admin/ImportData/GrowiArchive/ImportCollectionItem.jsx

@@ -200,7 +200,7 @@ export default class ImportCollectionItem extends React.Component {
 
     return (
       <div className="card border-light">
-        <div className="card-header bg-light">
+        <div className="card-header bg-light text-dark">
           <div className="d-flex justify-content-between align-items-center flex-wrap">
             {/* left */}
             {this.renderCheckbox()}

+ 6 - 6
apps/app/src/components/Admin/Notification/GlobalNotificationList.jsx

@@ -97,32 +97,32 @@ class GlobalNotificationList extends React.Component {
               <td>
                 <ul className="list-inline mb-0">
                   {notification.triggerEvents.includes('pageCreate') && (
-                    <li className="list-inline-item badge badge-pill badge-success">
+                    <li className="list-inline-item badge rounded-pill bg-success">
                       <i className="icon-doc"></i> CREATE
                     </li>
                   )}
                   {notification.triggerEvents.includes('pageEdit') && (
-                    <li className="list-inline-item badge badge-pill badge-warning">
+                    <li className="list-inline-item badge rounded-pill bg-warning text-dark">
                       <i className="icon-pencil"></i> EDIT
                     </li>
                   )}
                   {notification.triggerEvents.includes('pageMove') && (
-                    <li className="list-inline-item badge badge-pill badge-pink">
+                    <li className="list-inline-item badge rounded-pill bg-pink">
                       <i className="icon-action-redo"></i> MOVE
                     </li>
                   )}
                   {notification.triggerEvents.includes('pageDelete') && (
-                    <li className="list-inline-item badge badge-pill badge-danger">
+                    <li className="list-inline-item badge rounded-pill bg-danger">
                       <i className="icon-fire"></i> DELETE
                     </li>
                   )}
                   {notification.triggerEvents.includes('pageLike') && (
-                    <li className="list-inline-item badge badge-pill badge-info">
+                    <li className="list-inline-item badge rounded-pill bg-info">
                       <i className="fa fa-heart-o"></i> LIKE
                     </li>
                   )}
                   {notification.triggerEvents.includes('comment') && (
-                    <li className="list-inline-item badge badge-pill badge-secondary">
+                    <li className="list-inline-item badge rounded-pill bg-primary">
                       <i className="icon-fw icon-bubble"></i> POST
                     </li>
                   )}

+ 6 - 6
apps/app/src/components/Admin/Notification/ManageGlobalNotification.tsx

@@ -237,7 +237,7 @@ const ManageGlobalNotification = (props: Props): JSX.Element => {
                 checked={triggerEvents.has(TriggerEventType.CREATE)}
                 onChange={() => onChangeTriggerEvents(TriggerEventType.CREATE)}
               >
-                <span className="badge badge-pill badge-success">
+                <span className="badge rounded-pill bg-success">
                   <i className="icon-doc mr-1" /> CREATE
                 </span>
               </TriggerEventCheckBox>
@@ -249,7 +249,7 @@ const ManageGlobalNotification = (props: Props): JSX.Element => {
                 checked={triggerEvents.has(TriggerEventType.EDIT)}
                 onChange={() => onChangeTriggerEvents(TriggerEventType.EDIT)}
               >
-                <span className="badge badge-pill badge-warning">
+                <span className="badge rounded-pill bg-warning text-dark">
                   <i className="icon-pencil mr-1" />EDIT
                 </span>
               </TriggerEventCheckBox>
@@ -261,7 +261,7 @@ const ManageGlobalNotification = (props: Props): JSX.Element => {
                 checked={triggerEvents.has(TriggerEventType.MOVE)}
                 onChange={() => onChangeTriggerEvents(TriggerEventType.MOVE)}
               >
-                <span className="badge badge-pill badge-pink">
+                <span className="badge rounded-pill bg-pink">
                   <i className="icon-action-redo mr-1" />MOVE
                 </span>
               </TriggerEventCheckBox>
@@ -273,7 +273,7 @@ const ManageGlobalNotification = (props: Props): JSX.Element => {
                 checked={triggerEvents.has(TriggerEventType.DELETE)}
                 onChange={() => onChangeTriggerEvents(TriggerEventType.DELETE)}
               >
-                <span className="badge badge-pill badge-danger">
+                <span className="badge rounded-pill bg-danger">
                   <i className="icon-fire mr-1" />DELETE
                 </span>
               </TriggerEventCheckBox>
@@ -285,7 +285,7 @@ const ManageGlobalNotification = (props: Props): JSX.Element => {
                 checked={triggerEvents.has(TriggerEventType.LIKE)}
                 onChange={() => onChangeTriggerEvents(TriggerEventType.LIKE)}
               >
-                <span className="badge badge-pill badge-info">
+                <span className="badge rounded-pill bg-info">
                   <i className="fa fa-heart-o mr-1" />LIKE
                 </span>
               </TriggerEventCheckBox>
@@ -297,7 +297,7 @@ const ManageGlobalNotification = (props: Props): JSX.Element => {
                 checked={triggerEvents.has(TriggerEventType.POST)}
                 onChange={() => onChangeTriggerEvents(TriggerEventType.POST)}
               >
-                <span className="badge badge-pill badge-secondary">
+                <span className="badge rounded-pill bg-primary">
                   <i className="icon-bubble mr-1" />POST
                 </span>
               </TriggerEventCheckBox>

+ 3 - 3
apps/app/src/components/Admin/Notification/NotificationSetting.jsx

@@ -31,14 +31,14 @@ const Badge = ({ isEnabled }) => {
   const { t } = useTranslation('admin');
 
   return isEnabled
-    ? <span className="badge badge-success">{t('external_notification.enabled')}</span>
-    : <span className="badge badge-secondary">{t('external_notification.disabled')}</span>;
+    ? <span className="badge bg-success">{t('external_notification.enabled')}</span>
+    : <span className="badge bg-primary">{t('external_notification.disabled')}</span>;
 };
 
 const SkeletonListItem = () => (
   <li className="list-group-item">
     <h4 className="mb-2">
-      <span className="badge badge-secondary">――</span>
+      <span className="badge bg-primary">――</span>
       <span className="ml-2">...</span>
     </h4>
   </li>

+ 1 - 1
apps/app/src/components/Admin/Security/GitHubSecuritySettingContents.jsx

@@ -71,7 +71,7 @@ class GitHubSecurityManagementContents extends React.Component {
               </label>
             </div>
             {(!adminGeneralSecurityContainer.state.setupStrategies.includes('github') && isGitHubEnabled)
-              && <div className="badge badge-warning">{t('security_settings.setup_is_not_yet_complete')}</div>}
+              && <div className="badge bg-warning text-dark">{t('security_settings.setup_is_not_yet_complete')}</div>}
           </div>
         </div>
 

+ 1 - 1
apps/app/src/components/Admin/Security/GoogleSecuritySettingContents.jsx

@@ -69,7 +69,7 @@ class GoogleSecurityManagementContents extends React.Component {
               </label>
             </div>
             {(!adminGeneralSecurityContainer.state.setupStrategies.includes('google') && isGoogleEnabled)
-              && <div className="badge badge-warning">{t('security_settings.setup_is_not_yet_complete')}</div>}
+              && <div className="badge bg-warning text-dark">{t('security_settings.setup_is_not_yet_complete')}</div>}
           </div>
         </div>
 

+ 1 - 1
apps/app/src/components/Admin/Security/LdapSecuritySettingContents.jsx

@@ -73,7 +73,7 @@ class LdapSecuritySettingContents extends React.Component {
               </label>
             </div>
             {(!adminGeneralSecurityContainer.state.setupStrategies.includes('ldap') && isLdapEnabled)
-              && <div className="badge badge-warning">{t('security_settings.setup_is_not_yet_complete')}</div>}
+              && <div className="badge bg-warning text-dark">{t('security_settings.setup_is_not_yet_complete')}</div>}
           </div>
         </div>
 

+ 1 - 1
apps/app/src/components/Admin/Security/LocalSecuritySettingContents.jsx

@@ -78,7 +78,7 @@ class LocalSecuritySettingContents extends React.Component {
               </label>
             </div>
             {!adminGeneralSecurityContainer.state.setupStrategies.includes('local') && isLocalEnabled && (
-              <div className="badge badge-warning">{t('security_settings.setup_is_not_yet_complete')}</div>
+              <div className="badge bg-warning text-dark">{t('security_settings.setup_is_not_yet_complete')}</div>
             )}
           </div>
         </div>

+ 1 - 1
apps/app/src/components/Admin/Security/OidcSecuritySettingContents.jsx

@@ -63,7 +63,7 @@ class OidcSecurityManagementContents extends React.Component {
               </label>
             </div>
             {(!adminGeneralSecurityContainer.state.setupStrategies.includes('oidc') && isOidcEnabled)
-              && <div className="badge badge-warning">{t('security_settings.setup_is_not_yet_complete')}</div>}
+              && <div className="badge bg-warning text-dark">{t('security_settings.setup_is_not_yet_complete')}</div>}
           </div>
         </div>
 

+ 4 - 2
apps/app/src/components/Admin/Security/SamlSecuritySettingContents.jsx

@@ -80,7 +80,7 @@ class SamlSecurityManagementContents extends React.Component {
               </label>
             </div>
             {(!adminGeneralSecurityContainer.state.setupStrategies.includes('saml') && isSamlEnabled)
-              && <div className="badge badge-warning">{t('security_settings.setup_is_not_yet_complete')}</div>}
+              && <div className="badge bg-warning text-dark">{t('security_settings.setup_is_not_yet_complete')}</div>}
           </div>
         </div>
 
@@ -474,12 +474,14 @@ pWVdnzS1VCO8fKsJ7YYIr+JmHvseph3kFUOI5RqkCcMZlKUv83aUThsTHw==
                           Apache Lucene - Query Parser Syntax <i className="icon-share-alt"></i>
                         </a>.
                       </p>
+                      {/* TODO: use new accordion component */}
+                      {/* https://redmine.weseek.co.jp/issues/129222 */}
                       <div className="accordion" id="accordionExample">
                         <div className="card">
                           <div className="card-header p-1">
                             <h2 className="mb-0">
                               <button
-                                className="btn btn-link btn-block text-left"
+                                className="btn btn-link text-left"
                                 type="button"
                                 onClick={() => this.setState({ isHelpOpened: !this.state.isHelpOpened })}
                                 aria-expanded="true"

+ 1 - 1
apps/app/src/components/Admin/Security/ShareLinkSetting.tsx

@@ -129,7 +129,7 @@ const ShareLinkSetting = (props: ShareLinkSettingProps) => {
             </label>
           </div>
           {!setupStrategies.includes('local') && disableLinkSharing && (
-            <div className="badge badge-warning">{t('security_settings.setup_is_not_yet_complete')}</div>
+            <div className="badge bg-warning text-dark">{t('security_settings.setup_is_not_yet_complete')}</div>
           )}
         </div>
       </div>

+ 1 - 1
apps/app/src/components/Admin/SlackIntegration/BotTypeCard.jsx

@@ -54,7 +54,7 @@ const BotTypeCard = (props) => {
           {/*  A recommended badge is shown on official bot card, supplementary names are shown on Custom bot cards   */}
           { isBotTypeOfficial
             ? (
-              <span className="badge badge-info mr-2">
+              <span className="badge bg-info mr-2">
                 {t('admin:slack_integration.selecting_bot_types.recommended')}
               </span>
             ) : (

+ 2 - 2
apps/app/src/components/Admin/UserGroup/UserGroupTable.tsx

@@ -158,7 +158,7 @@ export const UserGroupTable: FC<Props> = (props: Props) => {
                 <td>
                   <ul className="list-inline">
                     {users != null && users.map((user) => {
-                      return <li key={user._id} className="list-inline-item badge badge-pill badge-warning">{user.username}</li>;
+                      return <li key={user._id} className="list-inline-item badge rounded-pill bg-warning text-dark">{user.username}</li>;
                     })}
                   </ul>
                 </td>
@@ -166,7 +166,7 @@ export const UserGroupTable: FC<Props> = (props: Props) => {
                   <ul className="list-inline">
                     {groupIdToChildGroupsMap[group._id] != null && groupIdToChildGroupsMap[group._id].map((group) => {
                       return (
-                        <li key={group._id} className="list-inline-item badge badge-success">
+                        <li key={group._id} className="list-inline-item badge bg-success">
                           {props.isAclEnabled
                             ? (
                               <Link href={`/admin/user-group-detail/${group._id}`}>{group.name}</Link>

+ 2 - 2
apps/app/src/components/Admin/UserManagement.tsx

@@ -90,7 +90,7 @@ const UserManagement = (props: UserManagementProps) => {
           onChange={() => clickHandler(status)}
         />
         <label className="form-label form-check-label" htmlFor={`c_${status}`}>
-          <span className={`badge badge-pill badge-${statusColor} d-inline-block vt mt-1`}>
+          <span className={`badge rounded-pill bg-${statusColor} d-inline-block vt mt-1`}>
             {statusLabel}
           </span>
         </label>
@@ -169,7 +169,7 @@ const UserManagement = (props: UserManagementProps) => {
               {renderCheckbox('all', 'All', 'secondary')}
               {renderCheckbox('registered', 'Approval Pending', 'info')}
               {renderCheckbox('active', 'Active', 'success')}
-              {renderCheckbox('suspended', 'Suspended', 'warning')}
+              {renderCheckbox('suspended', 'Suspended', 'warning text-dark')}
               {renderCheckbox('invited', 'Invited', 'pink')}
             </div>
             <div>

+ 2 - 2
apps/app/src/components/Admin/Users/ExternalAccountTable.tsx

@@ -84,8 +84,8 @@ const ExternalAccountTable = (props: ExternalAccountTableProps): JSX.Element =>
                 <td><strong>{ea.user.username}</strong></td>
                 <td>
                   {ea.user.password
-                    ? (<span className="badge badge-info">{t('user_management.set')}</span>)
-                    : (<span className="badge badge-warning">{t('user_management.unset')}</span>)
+                    ? (<span className="badge bg-info">{t('user_management.set')}</span>)
+                    : (<span className="badge bg-warning text-dark">{t('user_management.unset')}</span>)
                   }
                 </td>
                 <td>{dateFnsFormat(new Date(ea.createdAt), 'yyyy-MM-dd')}</td>

+ 9 - 9
apps/app/src/components/Admin/Users/UserTable.tsx

@@ -22,34 +22,34 @@ const UserTable = (props: UserTableProps) => {
   const { adminUsersContainer } = props;
 
   const getUserStatusLabel = (userStatus: number) => {
-    let additionalClassName = 'badge-info';
+    let additionalClassName = 'bg-info';
     let text = 'Approval Pending';
 
     switch (userStatus) {
       case 1:
-        additionalClassName = 'badge-info';
+        additionalClassName = 'bg-info';
         text = 'Approval Pending';
         break;
       case 2:
-        additionalClassName = 'badge-success';
+        additionalClassName = 'bg-success';
         text = 'Active';
         break;
       case 3:
-        additionalClassName = 'badge-warning';
+        additionalClassName = 'bg-warning text-dark';
         text = 'Suspended';
         break;
       case 4:
-        additionalClassName = 'badge-danger';
+        additionalClassName = 'bg-danger';
         text = 'Deleted';
         break;
       case 5:
-        additionalClassName = 'badge-pink';
+        additionalClassName = 'bg-pink';
         text = 'Invited';
         break;
     }
 
     return (
-      <span className={`badge badge-pill ${additionalClassName}`}>
+      <span className={`badge rounded-pill ${additionalClassName}`}>
         {text}
       </span>
     );
@@ -153,12 +153,12 @@ const UserTable = (props: UserTableProps) => {
                 <td>
                   {getUserStatusLabel(user.status)}
                   {(user.admin) && (
-                    <span className="badge badge-indigo badge-pill ml-2">
+                    <span className="badge bg-indigo rounded-pill ml-2">
                       {t('admin:user_management.user_table.administrator')}
                     </span>
                   )}
                   {(user.readOnly) && (
-                    <span className="badge badge-light badge-pill ml-2">
+                    <span className="badge bg-light text-dark rounded-pill ml-2">
                       {t('admin:user_management.user_table.read_only')}
                     </span>
                   )}

+ 1 - 1
apps/app/src/components/Common/CountBadge.tsx

@@ -10,7 +10,7 @@ const CountBadge: FC<CountProps> = (props:CountProps) => {
 
 
   return (
-    <span className="grw-count-badge px-2 badge badge-pill badge-light">
+    <span className="grw-count-badge px-2 badge rounded-pill bg-light text-dark">
       { count == null && <span className="text-muted">―</span> }
       { count != null && count + offset }
     </span>

+ 7 - 3
apps/app/src/components/CreateTemplateModal.jsx

@@ -52,9 +52,13 @@ const CreateTemplateModal = (props) => {
             <code>{parentPath}</code><br />
             { t('template.modal_label.Create template under') }
           </label>
-          <div className="card-deck">
-            {renderTemplateCard('children', '_template')}
-            {renderTemplateCard('decendants', '__template')}
+          <div className="row row-cols-2">
+            <div className="col">
+              {renderTemplateCard('children', '_template')}
+            </div>
+            <div className="col">
+              {renderTemplateCard('decendants', '__template')}
+            </div>
           </div>
         </div>
       </ModalBody>

+ 2 - 2
apps/app/src/components/CustomNavigation/CustomNav.tsx

@@ -49,9 +49,9 @@ export const CustomNavDropdown = (props: CustomNavDropdownProps): JSX.Element =>
   }, [onNavSelected]);
 
   return (
-    <div className="grw-custom-nav-dropdown btn-group btn-block">
+    <div className="grw-custom-nav-dropdown btn-group">
       <button
-        className="btn btn-outline-primary btn-lg btn-block dropdown-toggle text-right"
+        className="btn btn-outline-primary btn-lg dropdown-toggle text-right"
         type="button"
         data-toggle="dropdown"
         aria-haspopup="true"

+ 1 - 1
apps/app/src/components/DescendantsPageListModal.module.scss

@@ -1,6 +1,6 @@
 .grw-descendants-page-list-modal :global {
   .modal-header {
-    button.close {
+    button.btn-close {
       margin: auto 0rem auto auto;
     }
   }

+ 1 - 1
apps/app/src/components/InAppNotification/InAppNotificationDropdown.tsx

@@ -75,7 +75,7 @@ export const InAppNotificationDropdown = (): JSX.Element => {
 
   let badge;
   if (inAppNotificationUnreadStatusCount != null && inAppNotificationUnreadStatusCount > 0) {
-    badge = <span className="badge badge-pill badge-danger grw-notification-badge">{inAppNotificationUnreadStatusCount}</span>;
+    badge = <span className="badge rounded-pill bg-danger grw-notification-badge">{inAppNotificationUnreadStatusCount}</span>;
   }
   else {
     badge = '';

+ 1 - 1
apps/app/src/components/Layout/Admin.module.scss

@@ -101,7 +101,7 @@ $slack-work-space-name-card-border: #efc1f6;
     .supplementary-bot-name {
       font-size: 1rem;
     }
-    .badge-info {
+    .bg-info {
       font-size: 0.6rem;
     }
     .admin-bot-card {

+ 1 - 1
apps/app/src/components/Page/RenderTagLabels.tsx

@@ -28,7 +28,7 @@ const RenderTagLabels = React.memo((props: RenderTagLabelsProps) => {
     <>
       {tags.map((tag) => {
         return (
-          <a key={tag} href={`/_search?q=tag:${tag}`} className="grw-tag-label badge badge-secondary mr-2">
+          <a key={tag} href={`/_search?q=tag:${tag}`} className="grw-tag-label badge bg-primary mr-2">
             {tag}
           </a>
         );

+ 1 - 1
apps/app/src/components/PageAccessoriesModal/PageAccessoriesModal.module.scss

@@ -1,6 +1,6 @@
 .grw-page-accessories-modal :global {
   .modal-header {
-    button.close {
+    button.btn-close {
       margin: auto 0rem auto auto;
     }
   }

+ 1 - 1
apps/app/src/components/PageEditor/Cheatsheet.tsx

@@ -104,7 +104,7 @@ export const Cheatsheet = (): JSX.Element => {
         {renderCheetSheetElm(imageStr)}
 
         <hr />
-        <a href="/Sandbox" className="btn btn-info btn-block" target="_blank">
+        <a href="/Sandbox" className="btn btn-info" target="_blank">
           <i className="icon-share-alt" /> {t('sandbox.open_sandbox')}
         </a>
       </div>

+ 1 - 1
apps/app/src/components/PageEditor/Editor.tsx

@@ -340,7 +340,7 @@ const Editor: ForwardRefRenderFunction<IEditorMethods, EditorPropsType> = (props
           && (
             <button
               type="button"
-              className="btn btn-outline-secondary btn-block btn-open-dropzone"
+              className="btn btn-outline-secondary btn-open-dropzone"
               onClick={addAttachmentHandler}
             >
               <i className="icon-paper-clip" aria-hidden="true"></i>&nbsp;

+ 14 - 26
apps/app/src/components/PageEditor/PageEditor.tsx

@@ -1,5 +1,5 @@
 import React, {
-  useCallback, useEffect, useMemo, useRef, useState,
+  useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState,
 } from 'react';
 
 import EventEmitter from 'events';
@@ -116,7 +116,7 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
   const { mutate: mutateRemoteRevisionLastUpdateUser } = useRemoteRevisionLastUpdateUser();
 
   const { data: codemirrorEditor } = useCodeMirrorEditorMain(codeMirrorEditorContainerRef.current);
-  const { initDoc } = codemirrorEditor ?? {};
+  const { initDoc, focus: focusToEditor, setCaretLine } = codemirrorEditor ?? {};
 
   const { data: rendererOptions } = usePreviewOptions();
   const { mutate: mutateIsEnabledUnsavedWarning } = useIsEnabledUnsavedWarning();
@@ -492,21 +492,14 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
 
   // initial caret line
   useEffect(() => {
-    // TODO: implement
-    // refs: https://redmine.weseek.co.jp/issues/126516
-    // if (editorRef.current != null) {
-    //   editorRef.current.setCaretLine(0);
-    // }
-  }, []);
+    setCaretLine?.();
+  }, [setCaretLine]);
 
   // set handler to set caret line
   useEffect(() => {
     const handler = (line) => {
-      // TODO: implement
-      // refs: https://redmine.weseek.co.jp/issues/126516
-      // if (editorRef.current != null) {
-      //   editorRef.current.setCaretLine(line);
-      // }
+      setCaretLine?.(line);
+
       if (previewRef.current != null) {
         scrollSyncHelper.scrollPreview(previewRef.current, line);
       }
@@ -516,7 +509,7 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
     return function cleanup() {
       globalEmitter.removeListener('setCaretLine', handler);
     };
-  }, []);
+  }, [setCaretLine]);
 
   // set handler to save and return to View
   useEffect(() => {
@@ -528,13 +521,11 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
   }, [saveAndReturnToViewHandler]);
 
   // set handler to focus
-  useEffect(() => {
-    // TODO: implement
-    // refs: https://redmine.weseek.co.jp/issues/126516
-    // if (editorRef.current != null && editorMode === EditorMode.Editor) {
-    //   editorRef.current.forceToFocus();
-    // }
-  }, [editorMode]);
+  useLayoutEffect(() => {
+    if (editorMode === EditorMode.Editor) {
+      focusToEditor?.();
+    }
+  }, [editorMode, focusToEditor]);
 
   // Detect indent size from contents (only when users are allowed to change it)
   useEffect(() => {
@@ -556,11 +547,8 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
   // UnControlled CodeMirror value does not reset, so explicitly set the value to initialValue
   const onRouterChangeComplete = useCallback(() => {
     initDoc?.(initialValue);
-
-    // TODO: implement
-    // refs: https://redmine.weseek.co.jp/issues/126516
-    // editorRef.current?.setCaretLine(0);
-  }, [initDoc, initialValue]);
+    setCaretLine?.();
+  }, [initDoc, initialValue, setCaretLine]);
 
   useEffect(() => {
     router.events.on('routeChangeComplete', onRouterChangeComplete);

+ 2 - 2
apps/app/src/components/PageEditorByHackmd.tsx

@@ -380,12 +380,12 @@ export const PageEditorByHackmd = (): JSX.Element => {
 
           { isHackmdDocumentOutdated && (
             <div className="card border-warning">
-              <div className="card-header bg-warning"><i className="icon-fw icon-info"></i> {t('hackmd.draft_outdated')}</div>
+              <div className="card-header bg-warning text-dark"><i className="icon-fw icon-info"></i> {t('hackmd.draft_outdated')}</div>
               <div className="card-body text-center">
                 {t('hackmd.based_on_revision')}&nbsp;
                 { pageData != null && (
                   <Link href={urljoin(returnPathForURL(pageData.path, pageData._id), `?revisionId=${revisionIdHackmdSynced}`)} prefetch={false}>
-                    <span className="badge badge-secondary">{revisionIdHackmdSynced?.substr(-8)}</span>
+                    <span className="badge bg-primary">{revisionIdHackmdSynced?.substr(-8)}</span>
                   </Link>
                 )}
                 <div className="text-center mt-3">

+ 1 - 1
apps/app/src/components/PageHistory/Revision.tsx

@@ -64,7 +64,7 @@ export const Revision = (props: RevisionProps): JSX.Element => {
         <div className="ml-2">
           <div className="revision-history-author mb-1">
             <strong><Username user={author}></Username></strong>
-            { isLatestRevision && <span className="badge badge-info ml-2">Latest</span> }
+            { isLatestRevision && <span className="badge bg-info ml-2">Latest</span> }
           </div>
           <div className="mb-1">
             <UserDate dateTime={revision.createdAt} />

+ 1 - 1
apps/app/src/components/PagePresentationModal.module.scss

@@ -16,7 +16,7 @@
     z-index: 110; // over ".reveal .slides"
   }
 
-  .close {
+  .btn-close {
     display: inline-block;
     width: 3rem;
     height: 3rem;

+ 7 - 5
apps/app/src/components/PagePresentationModal.tsx

@@ -67,12 +67,14 @@ const PagePresentationModal = (): JSX.Element => {
       className={`grw-presentation-modal ${styles['grw-presentation-modal']}`}
     >
       <div className="grw-presentation-controls d-flex">
-        <button className="close btn-fullscreen" type="button" aria-label="fullscreen" onClick={toggleFullscreenHandler}>
-          <i className={`${fullscreen.active ? 'icon-size-actual' : 'icon-size-fullscreen'}`} aria-hidden></i>
-        </button>
-        <button className="close btn-close" type="button" aria-label="close" onClick={closeHandler}>
-          <i className="ti ti-close" aria-hidden></i>
+        <button
+          className={`btn ${fullscreen.active ? 'icon-size-actual' : 'icon-size-fullscreen'}`}
+          type="button"
+          aria-label="fullscreen"
+          onClick={toggleFullscreenHandler}
+        >
         </button>
+        <button className="btn-close" type="button" aria-label="Close" onClick={closeHandler}></button>
       </div>
       <ModalBody className="modal-body d-flex justify-content-center align-items-center">
         { rendererOptions != null && (

+ 2 - 2
apps/app/src/components/PageSideContents.tsx

@@ -45,7 +45,7 @@ export const PageSideContents = (props: PageSideContentsProps): JSX.Element => {
         {!isSharedUser && (
           <button
             type="button"
-            className="btn btn-block btn-outline-secondary grw-btn-page-accessories rounded-pill d-flex justify-content-between align-items-center"
+            className="btn btn-outline-secondary grw-btn-page-accessories rounded-pill d-flex justify-content-between align-items-center"
             onClick={() => openDescendantPageListModal(pagePath)}
             data-testid="pageListButton"
           >
@@ -68,7 +68,7 @@ export const PageSideContents = (props: PageSideContentsProps): JSX.Element => {
           <Link to="page-comments" offset={-120}>
             <button
               type="button"
-              className="btn btn-block btn-outline-secondary grw-btn-page-accessories rounded-pill d-flex justify-content-between align-items-center"
+              className="btn btn-outline-secondary grw-btn-page-accessories rounded-pill d-flex justify-content-between align-items-center"
               data-testid="page-comment-button"
             >
               <i className="icon-fw icon-bubbles grw-page-accessories-control-icon"></i>

+ 1 - 1
apps/app/src/components/PageStatusAlert.tsx

@@ -95,7 +95,7 @@ export const PageStatusAlert = (): JSX.Element => {
       : <span dangerouslySetInnerHTML={{ __html: `${usernameComponentToString} ${t('edited this page')}` }} />;
 
     return {
-      additionalClasses: ['bg-warning'],
+      additionalClasses: ['bg-warning text-dark'],
       label:
   <>
     <i className="icon-fw icon-bulb"></i>

+ 1 - 1
apps/app/src/components/PasswordResetExecutionForm.tsx

@@ -78,7 +78,7 @@ const PasswordResetExecutionForm: FC = () => {
         )}
       </div>
       <div>
-        <input name="reset-password-btn" className="btn btn-lg btn-primary btn-block" value={t('forgot_password.reset_password')} type="submit" />
+        <input name="reset-password-btn" className="btn btn-lg btn-primary" value={t('forgot_password.reset_password')} type="submit" />
       </div>
       <Link href="/login" prefetch={false}>
         <i className="icon-login mr-1"></i>{t('forgot_password.sign_in_instead')}

+ 1 - 1
apps/app/src/components/PasswordResetRequestForm.tsx

@@ -57,7 +57,7 @@ const PasswordResetRequestForm: FC = () => {
           </div>
           <div>
             <button
-              className="btn btn-lg btn-primary btn-block"
+              className="btn btn-lg btn-primary"
               type="submit"
               disabled={!isMailerSetup}
             >

+ 1 - 1
apps/app/src/components/Sidebar/Bookmarks/BookmarkContents.tsx

@@ -42,7 +42,7 @@ export const BookmarkContents = (): JSX.Element => {
       <div className="col-8 mb-2 ">
         <button
           type="button"
-          className="btn btn-block btn-outline-secondary rounded-pill d-flex justify-content-start align-middle"
+          className="btn btn-outline-secondary rounded-pill d-flex justify-content-start align-middle"
           onClick={onClickNewBookmarkFolder}
         >
           <FolderPlusIcon />

+ 1 - 1
apps/app/src/components/Sidebar/PersonalDropdown.tsx

@@ -67,7 +67,7 @@ export const PersonalDropdown = (): JSX.Element => {
               <i className="icon-envelope icon-fw"></i><span className="grw-email-sm">{currentUser.email}</span>
             </div>
 
-            <div className="btn-group btn-block mt-2" role="group">
+            <div className="btn-group mt-2" role="group">
               <Link
                 href={pagePathUtils.userHomepagePath(currentUser)}
                 className="btn btn-sm btn-outline-secondary col"

+ 1 - 1
apps/app/src/components/Sidebar/RecentChanges/RecentChangesSubstance.tsx

@@ -71,7 +71,7 @@ const PageItem = memo(({ page, isSmall }: PageItemProps): JSX.Element => {
       <Link
         key={tag.name}
         href={`/_search?q=tag:${tag.name}`}
-        className="grw-tag-label badge badge-secondary mr-2 small"
+        className="grw-tag-label badge bg-primary mr-2 small"
         prefetch={false}
       >
         {tag.name}

+ 1 - 1
apps/app/src/components/TagCloudBox.tsx

@@ -33,7 +33,7 @@ const TagCloudBox: FC<Props> = memo((props:(Props & typeof defaultProps)) => {
       <Link
         key={tag.name}
         href={`${url.pathname}${url.search}`}
-        className="grw-tag-label badge badge-secondary mr-2"
+        className="grw-tag-label badge bg-primary mr-2"
         prefetch={false}
       >
         {tagNameFormat}

+ 1 - 1
apps/app/src/components/TagList.tsx

@@ -44,7 +44,7 @@ const TagList: FC<TagListProps> = (props:(TagListProps & typeof defaultProps)) =
           prefetch={false}
         >
           <div className="text-truncate list-tag-name">{tag.name}</div>
-          <div className="ml-4 my-auto py-1 px-2 list-tag-count badge badge-secondary text-white">{tag.count}</div>
+          <div className="ml-4 my-auto py-1 px-2 list-tag-count badge bg-primary">{tag.count}</div>
         </Link>
       );
     });

+ 1 - 1
apps/app/src/features/growi-plugin/client/components/Admin/PluginsExtensionPageContents/PluginCard.tsx

@@ -119,7 +119,7 @@ export const PluginCard = (props: Props): JSX.Element => {
           </div>
         </div>
       </div>
-      <div className="card-footer px-5 border-top-0 mp-bg-light-blue">
+      <div className="card-footer px-5 border-top-0">
         <p className="d-flex justify-content-between align-self-center mb-0">
         </p>
       </div>

+ 2 - 2
apps/app/src/features/questionnaire/client/components/ProactiveQuestionnaireModal.tsx

@@ -93,7 +93,7 @@ const ProactiveQuestionnaireModal = (props: ModalProps): JSX.Element => {
             <form className="px-5" onSubmit={submitHandler}>
               <div className="row mt-5">
                 <label className="col-sm-5 col-form-label" htmlFor="satisfaction">
-                  <span className="badge badge-primary mr-2">{t('questionnaire_modal.required')}</span>{t('questionnaire_modal.satisfaction_with_growi')}
+                  <span className="badge bg-primary mr-2">{t('questionnaire_modal.required')}</span>{t('questionnaire_modal.satisfaction_with_growi')}
                 </label>
                 <select className="col-sm-7 form-control" name="satisfaction" id="satisfaction" required>
                   <option value="">▼ {t('Select')}</option>
@@ -130,7 +130,7 @@ const ProactiveQuestionnaireModal = (props: ModalProps): JSX.Element => {
               </div>
               <div className="row mt-3">
                 <label className="col-sm-5 col-form-label" htmlFor="commentText">
-                  <span className="badge badge-primary mr-2">{t('questionnaire_modal.required')}</span>{t('questionnaire_modal.comment_on_growi')}
+                  <span className="badge bg-primary mr-2">{t('questionnaire_modal.required')}</span>{t('questionnaire_modal.comment_on_growi')}
                 </label>
                 <textarea className="col-sm-7 form-control" name="commentText" id="commentText" rows={5} required />
               </div>

+ 1 - 1
apps/app/src/features/questionnaire/client/components/Question.tsx

@@ -21,7 +21,7 @@ const Question = ({ question, inputNamePrefix }: QuestionProps): JSX.Element =>
         </span>
       </div>
       <div className="col-6 d-flex align-items-center pl-0">
-        <div className="btn-group btn-group-toggle flex-fill grw-questionnaire-btn-group" data-toggle="buttons">
+        <div className="btn-group flex-fill grw-questionnaire-btn-group">
           <label className="form-label btn btn-outline-primary active mr-4 rounded">
             <input type="radio" name={`${inputNamePrefix + question._id}`} id={`${question._id}-noAnswer`} value="0" defaultChecked /> -
           </label>

+ 2 - 4
apps/app/src/features/questionnaire/client/components/QuestionnaireToast.tsx

@@ -72,11 +72,9 @@ const QuestionnaireToast = ({ questionnaireOrder }: QuestionnaireToastProps): JS
     <div className={`toast ${isOpen ? 'show' : 'hide'}`}>
       <div className="toast-header bg-primary">
         <strong className="mr-auto text-light">{questionnaireOrderShortTitle}</strong>
-        <button type="button" className="ml-2 mb-1 close" onClick={closeBtnClickHandler}>
-          <span aria-hidden="true" className="text-light">&times;</span>
-        </button>
+        <button type="button" className="ml-2 mb-1 btn-close" onClick={closeBtnClickHandler} aria-label="Close"></button>
       </div>
-      <div className="toast-body bg-light d-flex justify-content-end">
+      <div className="toast-body bg-light text-dark d-flex justify-content-end">
         <button type="button" className="btn btn-secondary mr-3" onClick={answerBtnClickHandler}>{t('questionnaire.answer')}</button>
         <button type="button" className="btn btn-secondary" onClick={denyBtnClickHandler}>{t('questionnaire.deny')}</button>
       </div>

+ 3 - 1
apps/app/src/styles/_override-rbt.scss

@@ -9,8 +9,10 @@
   }
 }
 
+// TODO: check padding when upgrade react-bootstrap-typeahead v6
+// https://redmine.weseek.co.jp/issues/129103
 .rbt-input-wrapper {
-  .close.rbt-close {
+  .btn-close.rbt-close {
     // default bootstrap .close has padding 0
     padding: 3px 7px;
   }

+ 2 - 2
apps/app/src/styles/theme/_hsl-reboot-bootstrap-theme-colors.scss

@@ -96,11 +96,11 @@ $hsl-colors: (
 }
 
 @each $color, $value in $hsl-colors {
-  .badge-#{$color} {
+  .bg-#{$color} {
     @include hsl-badge.badge-variant($value);
   }
 
-  a.badge-#{$color}  {
+  a.bg-#{$color}  {
     @include hsl-badge.badge-variant($value);
   }
 }

+ 2 - 2
apps/app/src/styles/theme/_reboot-bootstrap-theme-colors.scss

@@ -92,10 +92,10 @@
 }
 
 @each $color, $value in $theme-colors {
-  .badge-#{$color} {
+  .bg-#{$color} {
     @include badge-variant($value);
   }
-  a.badge-#{$color} {
+  a.bg-#{$color} {
     @include badge-variant($value);
   }
 }

+ 2 - 2
apps/app/src/styles/theme/apply-colors.scss

@@ -340,7 +340,7 @@ ul.pagination {
     .modal-title {
       color: $color-modal-header;
     }
-    .close {
+    .btn-close {
       color: $color-modal-header;
       opacity: 0.5;
 
@@ -361,7 +361,7 @@ ul.pagination {
 
 .grw-page-accessories-modal,.grw-descendants-page-list-modal {
   .modal-header {
-    .close {
+    .btn-close {
       color: #{hsl.contrast(var(--bgcolor-global))};
     }
   }

+ 1 - 0
packages/editor/package.json

@@ -32,6 +32,7 @@
     "bootstrap": "^5.3.1",
     "codemirror": "^6.0.1",
     "eslint-plugin-react-refresh": "^0.4.1",
+    "react-hook-form": "^7.45.4",
     "swr": "^2.0.3"
   }
 }

+ 1 - 1
packages/editor/src/components/playground/Playground.tsx

@@ -20,7 +20,7 @@ export const Playground = (): JSX.Element => {
         <div className="flex-expand-vert">
           <CodeMirrorEditorContainer ref={containerRef} />
         </div>
-        <div className="flex-expand-vert d-none d-lg-flex bg-light border-start border-dark-subtle p-3">
+        <div className="flex-expand-vert d-none d-lg-flex bg-light text-dark border-start border-dark-subtle p-3">
           <PlaygroundController />
         </div>
       </div>

+ 60 - 12
packages/editor/src/components/playground/PlaygroundController.tsx

@@ -1,8 +1,10 @@
 import { useCallback } from 'react';
 
+import { useForm } from 'react-hook-form';
+
 import { useCodeMirrorEditorMain } from '../../stores';
 
-export const PlaygroundController = (): JSX.Element => {
+export const InitEditorValueRow = (): JSX.Element => {
 
   const { data } = useCodeMirrorEditorMain();
 
@@ -12,18 +14,64 @@ export const PlaygroundController = (): JSX.Element => {
   }, [initDoc]);
 
   return (
-    <>
-      <div className="row">
-        <div className="column">
-          <button
-            type="button"
-            className="btn btn-outline-secondary"
-            onClick={() => initEditorValue()}
-          >
-            Initialize editor value
-          </button>
+    <div className="row">
+      <div className="col">
+        <button
+          type="button"
+          className="btn btn-outline-secondary"
+          onClick={() => initEditorValue()}
+        >
+          Initialize editor value
+        </button>
+      </div>
+    </div>
+  );
+};
+
+type SetCaretLineRowFormData = {
+  lineNumber: number | string;
+};
+
+export const SetCaretLineRow = (): JSX.Element => {
+
+  const { data } = useCodeMirrorEditorMain();
+  const { register, handleSubmit } = useForm<SetCaretLineRowFormData>({
+    defaultValues: {
+      lineNumber: 1,
+    },
+  });
+
+  const setCaretLine = data?.setCaretLine;
+  const onSubmit = handleSubmit((submitData) => {
+    const lineNumber = Number(submitData.lineNumber) || 1;
+    setCaretLine?.(lineNumber);
+  });
+
+  return (
+    <form className="row mt-3" onSubmit={onSubmit}>
+      <div className="col">
+        <div className="input-group">
+          <input
+            {...register('lineNumber')}
+            type="number"
+            className="form-control"
+            placeholder="Input line number"
+            aria-label="line number"
+            aria-describedby="button-set-cursor"
+          />
+          <button type="submit" className="btn btn-outline-secondary" id="button-set-cursor">Set the cursor</button>
         </div>
       </div>
-    </>
+    </form>
+
+  );
+};
+
+export const PlaygroundController = (): JSX.Element => {
+  return (
+    <div className="container">
+      <InitEditorValueRow />
+      <SetCaretLineRow />
+    </div>
   );
 };

+ 26 - 0
packages/editor/src/services/codemirror-editor/use-codemirror-editor.ts

@@ -12,6 +12,8 @@ export type UseCodeMirrorEditor = UseCodeMirror;
 type UseCodeMirrorEditorUtils = {
   initState: (config?: EditorStateConfig) => void,
   initDoc: (doc?: string) => void,
+  focus: () => void,
+  setCaretLine: (lineNumber?: number) => void,
 }
 
 export type UseCodeMirrorEditorResponse = UseCodeMirrorEditorStates & UseCodeMirrorEditorUtils;
@@ -56,6 +58,28 @@ export const useCodeMirrorEditor = (props?: UseCodeMirrorEditor): UseCodeMirrorE
     initState({ doc });
   }, [initState]);
 
+  // implement focus method
+  const focus = useCallback((): void => {
+    view?.focus();
+  }, [view]);
+
+  // implement setCaretLine method
+  const setCaretLine = useCallback((lineNumber?: number): void => {
+    if (view == null) {
+      return;
+    }
+
+    const posOfLineEnd = view.state.doc.line(lineNumber ?? 1).to;
+    view.dispatch({
+      selection: {
+        anchor: posOfLineEnd,
+        head: posOfLineEnd,
+      },
+    });
+    // focus
+    view.focus();
+  }, [view]);
+
   useEffect(() => {
     if (props?.container != null) {
       setContainer(props.container);
@@ -66,5 +90,7 @@ export const useCodeMirrorEditor = (props?: UseCodeMirrorEditor): UseCodeMirrorE
     ...codemirror,
     initState,
     initDoc,
+    focus,
+    setCaretLine,
   };
 };

+ 23 - 0
packages/editor/turbo.json

@@ -0,0 +1,23 @@
+{
+  "extends": ["//"],
+  "pipeline": {
+    "build": {
+      "dependsOn": ["@growi/core#build"],
+      "outputs": ["dist/**"],
+      "outputMode": "new-only"
+    },
+    "dev": {
+      "dependsOn": ["@growi/core#dev"],
+      "outputs": ["dist/**"],
+      "outputMode": "new-only"
+    },
+    "lint": {
+      "dependsOn": ["@growi/core#dev"]
+    },
+    "serve": {
+      "dependsOn": ["@growi/core#dev"],
+      "cache": false,
+      "persistent": true
+    }
+  }
+}

+ 1 - 1
packages/remark-lsx/src/client/components/Lsx.tsx

@@ -111,7 +111,7 @@ const LsxSubstance = React.memo(({
         <div className="col-12 col-sm-8 d-flex flex-column align-items-center lsx-load-more-container">
           <button
             type="button"
-            className="btn btn btn-block btn-outline-secondary btn-load-more"
+            className="btn btn btn-outline-secondary btn-load-more"
             onClick={() => setSize(size => size + 1)}
           >
             Load more<br />

+ 2 - 2
packages/ui/src/components/Attachment.tsx

@@ -36,8 +36,8 @@ export const Attachment = (props: AttachmentProps): JSX.Element => {
       </a>
     )
     : '';
-  const fileType = <span className="attachment-filetype badge badge-pill badge-secondary">{attachment.fileFormat}</span>;
-  const fileInUse = (inUse) ? <span className="attachment-in-use badge badge-pill badge-info">In Use</span> : '';
+  const fileType = <span className="attachment-filetype badge rounded-pill bg-primary">{attachment.fileFormat}</span>;
+  const fileInUse = (inUse) ? <span className="attachment-in-use badge rounded-pill bg-info">In Use</span> : '';
 
   return (
     <div className="attachment mb-2">

+ 2 - 2
packages/ui/src/components/PagePath/PageListMeta.tsx

@@ -70,13 +70,13 @@ export const PageListMeta: FC<PageListMetaProps> = (props: PageListMetaProps) =>
   // top check
   let topLabel;
   if (isTopPage(page.path)) {
-    topLabel = <span className={`badge badge-info ${shouldSpaceOutIcon ? 'mr-2' : ''} top-label`}>TOP</span>;
+    topLabel = <span className={`badge bg-info ${shouldSpaceOutIcon ? 'mr-2' : ''} top-label`}>TOP</span>;
   }
 
   // template check
   let templateLabel;
   if (checkTemplatePath(page.path)) {
-    templateLabel = <span className={`badge badge-info ${shouldSpaceOutIcon ? 'mr-2' : ''}`}>TMPL</span>;
+    templateLabel = <span className={`badge bg-info ${shouldSpaceOutIcon ? 'mr-2' : ''}`}>TMPL</span>;
   }
 
   let commentCount;

+ 0 - 13
turbo.json

@@ -19,11 +19,6 @@
       "cache": false
     },
 
-    "@growi/editor#build": {
-      "dependsOn": ["@growi/core#build"],
-      "outputs": ["dist/**"],
-      "outputMode": "new-only"
-    },
     "@growi/pluginkit#build": {
       "dependsOn": ["@growi/core#build"],
       "outputs": ["dist/**"],
@@ -73,11 +68,6 @@
       "outputMode": "new-only"
     },
 
-    "@growi/editor#dev": {
-      "dependsOn": ["@growi/core#dev"],
-      "outputs": ["dist/**"],
-      "outputMode": "new-only"
-    },
     "@growi/pluginkit#dev": {
       "dependsOn": ["@growi/core#dev"],
       "outputs": ["dist/**"],
@@ -154,9 +144,6 @@
       "persistent": true
     },
 
-    "@growi/editor#lint": {
-      "dependsOn": ["@growi/core#dev"]
-    },
     "@growi/pluginkit#lint": {
       "dependsOn": ["@growi/core#dev"]
     },

+ 5 - 0
yarn.lock

@@ -14333,6 +14333,11 @@ react-fast-compare@^3.0.1:
   resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
   integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==
 
+react-hook-form@^7.45.4:
+  version "7.45.4"
+  resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.45.4.tgz#73d228b704026ae95d7e5f7b207a681b173ec62a"
+  integrity sha512-HGDV1JOOBPZj10LB3+OZgfDBTn+IeEsNOKiq/cxbQAIbKaiJUe/KV8DBUzsx0Gx/7IG/orWqRRm736JwOfUSWQ==
+
 react-hotkeys@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/react-hotkeys/-/react-hotkeys-2.0.0.tgz#a7719c7340cbba888b0e9184f806a9ec0ac2c53f"