Просмотр исходного кода

Merge branch 'dev/7.0.x' into imprv/126530-130491-save-mod-enter

reiji-h 2 лет назад
Родитель
Сommit
7e31ca89ca
82 измененных файлов с 1307 добавлено и 808 удалено
  1. 36 1
      CHANGELOG.md
  2. 0 0
      apps/app/_obsolete/src/styles/theme/_apply-colors-dark.scss
  3. 0 0
      apps/app/_obsolete/src/styles/theme/_apply-colors-light.scss
  4. 0 0
      apps/app/_obsolete/src/styles/theme/_hsl-functions.scss
  5. 0 0
      apps/app/_obsolete/src/styles/theme/_hsl-reboot-bootstrap-theme-colors.scss
  6. 0 0
      apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-border-colors.scss
  7. 0 0
      apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-buttons.scss
  8. 0 0
      apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-colors.scss
  9. 0 0
      apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-dropdown.scss
  10. 0 0
      apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-nav.scss
  11. 0 0
      apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-tables.scss
  12. 0 0
      apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-text.scss
  13. 0 0
      apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-theme-colors.scss
  14. 0 0
      apps/app/_obsolete/src/styles/theme/_reboot-toastr-colors.scss
  15. 0 0
      apps/app/_obsolete/src/styles/theme/apply-colors.scss
  16. 0 0
      apps/app/_obsolete/src/styles/theme/mixins/_count-badge.scss
  17. 0 0
      apps/app/_obsolete/src/styles/theme/mixins/_hsl-badge.scss
  18. 0 0
      apps/app/_obsolete/src/styles/theme/mixins/_hsl-button.scss
  19. 0 0
      apps/app/_obsolete/src/styles/theme/mixins/_list-group.scss
  20. 0 0
      apps/app/_obsolete/src/styles/theme/mixins/_page-editor-mode-manager.scss
  21. 5 1
      apps/app/public/static/locales/en_US/admin.json
  22. 1 0
      apps/app/public/static/locales/en_US/translation.json
  23. 7 2
      apps/app/public/static/locales/ja_JP/admin.json
  24. 1 0
      apps/app/public/static/locales/ja_JP/translation.json
  25. 5 1
      apps/app/public/static/locales/zh_CN/admin.json
  26. 1 0
      apps/app/public/static/locales/zh_CN/translation.json
  27. 21 2
      apps/app/src/client/services/AdminCustomizeContainer.js
  28. 4 0
      apps/app/src/components/Admin/Customize/Customize.jsx
  29. 0 28
      apps/app/src/components/Admin/Customize/CustomizeFunctionSetting.tsx
  30. 70 0
      apps/app/src/components/Admin/Customize/CustomizePresentationSetting.tsx
  31. 1 2
      apps/app/src/components/Bookmarks/BookmarkFolderItem.tsx
  32. 4 2
      apps/app/src/components/Bookmarks/BookmarkFolderTree.module.scss
  33. 0 15
      apps/app/src/components/Icons/TriangleIcon.tsx
  34. 1 1
      apps/app/src/components/InAppNotification/InAppNotificationDropdown.tsx
  35. 0 1
      apps/app/src/components/PagePresentationModal.module.scss
  36. 3 2
      apps/app/src/components/Sidebar/Custom/CustomSidebar.tsx
  37. 6 1
      apps/app/src/components/Sidebar/Custom/CustomSidebarNotFound.tsx
  38. 1 1
      apps/app/src/components/Sidebar/Custom/CustomSidebarSubstance.tsx
  39. 37 0
      apps/app/src/components/Sidebar/PageTree/Item.module.scss
  40. 7 3
      apps/app/src/components/Sidebar/PageTree/Item.tsx
  41. 11 2
      apps/app/src/components/Sidebar/PageTree/ItemsTree.module.scss
  42. 46 46
      apps/app/src/components/Sidebar/PersonalDropdown.tsx
  43. 33 5
      apps/app/src/components/Sidebar/Sidebar.module.scss
  44. 68 29
      apps/app/src/components/Sidebar/SidebarNav.module.scss
  45. 6 12
      apps/app/src/components/Sidebar/SidebarNav.tsx
  46. 0 1
      apps/app/src/pages/_app.page.tsx
  47. 8 1
      apps/app/src/server/.node-dev.json
  48. 24 4
      apps/app/src/server/routes/apiv3/customize-setting.js
  49. 26 21
      apps/app/src/stores/page.tsx
  50. 3 6
      apps/app/src/styles/_variables.scss
  51. 1 0
      apps/app/src/styles/font-icons.scss
  52. 26 1
      apps/app/src/styles/organisms/_wiki.scss
  53. 3 0
      apps/app/src/utils/axios.ts
  54. 0 1
      apps/app/vite.styles-prebuilt.config.ts
  55. 3 0
      packages/core/scss/_growi-official-colors.scss
  56. 1 0
      packages/core/scss/bootstrap/_init-stage-1.scss
  57. 3 0
      packages/core/scss/bootstrap/_init-stage-2.scss
  58. 0 13
      packages/core/scss/bootstrap/_init.scss
  59. 3 28
      packages/core/scss/bootstrap/_variables.scss
  60. 0 0
      packages/core/scss/bootstrap/apply.scss
  61. 8 0
      packages/core/scss/bootstrap/init.scss
  62. 15 0
      packages/core/scss/bootstrap/theming/_buttons.scss
  63. 4 0
      packages/core/scss/bootstrap/theming/_list-group.scss
  64. 5 0
      packages/core/scss/bootstrap/theming/_pagination.scss
  65. 4 0
      packages/core/scss/bootstrap/theming/_progress.scss
  66. 41 0
      packages/core/scss/bootstrap/theming/_root-dark.scss
  67. 32 0
      packages/core/scss/bootstrap/theming/_root-light.scss
  68. 31 0
      packages/core/scss/bootstrap/theming/_root.scss
  69. 5 0
      packages/core/scss/bootstrap/theming/_tables.scss
  70. 16 0
      packages/core/scss/bootstrap/theming/_variables.scss
  71. 5 0
      packages/core/scss/bootstrap/theming/apply.scss
  72. 31 0
      packages/core/scss/bootstrap/theming/utils/_color-palette.scss
  73. 4 0
      packages/core/scss/bootstrap/utilities.scss
  74. 1 0
      packages/editor/src/main.scss
  75. 3 3
      packages/presentation/package.json
  76. 2 2
      packages/presentation/src/components/Presentation.module.scss
  77. 1 0
      packages/preset-themes/package.json
  78. 0 26
      packages/preset-themes/src/styles/_variables.scss
  79. 256 256
      packages/preset-themes/src/styles/default.scss
  80. 334 258
      packages/preset-themes/src/styles/mono-blue.scss
  81. 31 29
      packages/preset-themes/vite.themes.config.ts
  82. 2 1
      turbo.json

+ 36 - 1
CHANGELOG.md

@@ -1,6 +1,6 @@
 # Changelog
 # Changelog
 
 
-## [Unreleased](https://github.com/weseek/growi/compare/v6.1.12...HEAD)
+## [Unreleased](https://github.com/weseek/growi/compare/v6.2.0...HEAD)
 
 
 *Please do not manually update this file. We've automated the process.*
 *Please do not manually update this file. We've automated the process.*
 
 
@@ -23,6 +23,41 @@
 - fix: Do not work img tag if use style property (#7988) @jam411
 - fix: Do not work img tag if use style property (#7988) @jam411
 - fix: "Searching..." label appearing unnecessarily (#7990) @yuki-takei
 - fix: "Searching..." label appearing unnecessarily (#7990) @yuki-takei
 
 
+## [v6.2.0](https://github.com/weseek/growi/compare/v6.1.12...v6.2.0) - 2023-09-14
+
+### 💎 Features
+
+- feat: Presentation preview and support Marp  (#8029) @reiji-h
+
+### 🚀 Improvement
+
+- imprv: Able to customize users homepage deletion (#7921) @yuki-takei
+- imprv: Search behavior (#8069) @yuki-takei
+- imprv: Add CSP style-src for Safari and Content-Disposition of attachment (#8049) @ykanematsu
+- imprv: Correct update message (#8040) @reiji-h
+- imprv: Add installed date to questionnaire answer (#7971) @TatsuyaIse
+- imprv: Show modal when you delete plugin (#7875) @soumaeda
+- imprv: i18n resetting password mail body (#8058) @meiri-k
+- imprv: Create Japanese ejs files (#7957) @meiri-k
+- imprv: Clean up old toastr (#7949) @jam411
+- imprv: Persist the installed date in the Config collection (#7936) @TatsuyaIse
+
+### 🐛 Bug Fixes
+
+- fix: Pages can be created under a non-existent user page (#7974) @miya
+- fix: Pages can be created under a non-existent user page (During attachment upload) (#8001) @miya
+- fix: Type safe implementation for objects imported from ElasticsearchClient (#7862) @miya
+- fix: Consider an empty page when renaming and duplicating (#7979) @yuki-takei
+- fix: Remove redundant toastSuccess for pasted attachments (#8044) @jam411
+- fix: Fixing swagger for tag update api (#8010) @miya
+- fix: Modification of links in the docs (#8004) @miya
+
+### 🧰 Maintenance
+
+- support: Omit core-js v2 (#7944) @yuki-takei
+- support: Improve build settings (#7919) @yuki-takei
+- support: Url to join to the slack team (#8073) @WNomunomu
+
 ## [v6.1.12](https://github.com/weseek/growi/compare/v6.1.11...v6.1.12) - 2023-08-14
 ## [v6.1.12](https://github.com/weseek/growi/compare/v6.1.11...v6.1.12) - 2023-08-14
 
 
 ### 🐛 Bug Fixes
 ### 🐛 Bug Fixes

+ 0 - 0
apps/app/src/styles/theme/_apply-colors-dark.scss → apps/app/_obsolete/src/styles/theme/_apply-colors-dark.scss


+ 0 - 0
apps/app/src/styles/theme/_apply-colors-light.scss → apps/app/_obsolete/src/styles/theme/_apply-colors-light.scss


+ 0 - 0
apps/app/src/styles/theme/_hsl-functions.scss → apps/app/_obsolete/src/styles/theme/_hsl-functions.scss


+ 0 - 0
apps/app/src/styles/theme/_hsl-reboot-bootstrap-theme-colors.scss → apps/app/_obsolete/src/styles/theme/_hsl-reboot-bootstrap-theme-colors.scss


+ 0 - 0
apps/app/src/styles/theme/_reboot-bootstrap-border-colors.scss → apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-border-colors.scss


+ 0 - 0
apps/app/src/styles/theme/_reboot-bootstrap-buttons.scss → apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-buttons.scss


+ 0 - 0
apps/app/src/styles/theme/_reboot-bootstrap-colors.scss → apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-colors.scss


+ 0 - 0
apps/app/src/styles/theme/_reboot-bootstrap-dropdown.scss → apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-dropdown.scss


+ 0 - 0
apps/app/src/styles/theme/_reboot-bootstrap-nav.scss → apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-nav.scss


+ 0 - 0
apps/app/src/styles/theme/_reboot-bootstrap-tables.scss → apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-tables.scss


+ 0 - 0
apps/app/src/styles/theme/_reboot-bootstrap-text.scss → apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-text.scss


+ 0 - 0
apps/app/src/styles/theme/_reboot-bootstrap-theme-colors.scss → apps/app/_obsolete/src/styles/theme/_reboot-bootstrap-theme-colors.scss


+ 0 - 0
apps/app/src/styles/theme/_reboot-toastr-colors.scss → apps/app/_obsolete/src/styles/theme/_reboot-toastr-colors.scss


+ 0 - 0
apps/app/src/styles/theme/apply-colors.scss → apps/app/_obsolete/src/styles/theme/apply-colors.scss


+ 0 - 0
apps/app/src/styles/theme/mixins/_count-badge.scss → apps/app/_obsolete/src/styles/theme/mixins/_count-badge.scss


+ 0 - 0
apps/app/src/styles/theme/mixins/_hsl-badge.scss → apps/app/_obsolete/src/styles/theme/mixins/_hsl-badge.scss


+ 0 - 0
apps/app/src/styles/theme/mixins/_hsl-button.scss → apps/app/_obsolete/src/styles/theme/mixins/_hsl-button.scss


+ 0 - 0
apps/app/src/styles/theme/mixins/_list-group.scss → apps/app/_obsolete/src/styles/theme/mixins/_list-group.scss


+ 0 - 0
apps/app/src/styles/theme/mixins/_page-editor-mode-manager.scss → apps/app/_obsolete/src/styles/theme/mixins/_page-editor-mode-manager.scss


+ 5 - 1
apps/app/public/static/locales/en_US/admin.json

@@ -480,7 +480,10 @@
       "show_all_reply_comments": "Show all reply comments",
       "show_all_reply_comments": "Show all reply comments",
       "show_all_reply_comments_desc": "When the setting value is off, comments other than the latest two are omitted.",
       "show_all_reply_comments_desc": "When the setting value is off, comments other than the latest two are omitted.",
       "select_search_scope_children_as_default": "Select 'Only children of this tree' as default value of search range",
       "select_search_scope_children_as_default": "Select 'Only children of this tree' as default value of search range",
-      "select_search_scope_children_as_default_desc": "When the setting value is off, 'All pages' is used as default value of search range.",
+      "select_search_scope_children_as_default_desc": "When the setting value is off, 'All pages' is used as default value of search range."
+    },
+      "presentation": "Presentation",
+    "presentation_options": {
       "enable_marp": "Enable Marp ",
       "enable_marp": "Enable Marp ",
       "enable_marp_desc": "Marp can be used in presentation preview. This option may make you vulnerable to XSS.",
       "enable_marp_desc": "Marp can be used in presentation preview. This option may make you vulnerable to XSS.",
       "marp_official_site": "The Marp Official Site",
       "marp_official_site": "The Marp Official Site",
@@ -499,6 +502,7 @@
     "write_css": "You can write CSS that is applied to whole system.",
     "write_css": "You can write CSS that is applied to whole system.",
     "ctrl_space": "Ctrl+Space to autocomplete",
     "ctrl_space": "Ctrl+Space to autocomplete",
     "custom_script": "Custom script",
     "custom_script": "Custom script",
+    "custom_presentation": "Custom presentation",
     "write_java": "You can write Javascript that is applied to whole system.",
     "write_java": "You can write Javascript that is applied to whole system.",
     "reflect_change": "You need to reload the page to reflect the change.",
     "reflect_change": "You need to reload the page to reflect the change.",
     "custom_logo" : "Custom Logo",
     "custom_logo" : "Custom Logo",

+ 1 - 0
apps/app/public/static/locales/en_US/translation.json

@@ -66,6 +66,7 @@
   "No users have liked this yet.": "No users have liked this yet.",
   "No users have liked this yet.": "No users have liked this yet.",
   "No users have bookmarked yet": "No users have bookmarked yet",
   "No users have bookmarked yet": "No users have bookmarked yet",
   "Create Archive Page": "Create Archive Page",
   "Create Archive Page": "Create Archive Page",
+  "Create Sidebar Page": "Create <strong>/Sidebar</strong> Page",
   "File type": "File type",
   "File type": "File type",
   "Target page": "Target page",
   "Target page": "Target page",
   "Include Attachment File": "Include Attachment File",
   "Include Attachment File": "Include Attachment File",

+ 7 - 2
apps/app/public/static/locales/ja_JP/admin.json

@@ -488,7 +488,11 @@
       "show_all_reply_comments": "返信コメントを全て表示する",
       "show_all_reply_comments": "返信コメントを全て表示する",
       "show_all_reply_comments_desc": "OFFの場合、最新2件のコメント以外が省略されます。",
       "show_all_reply_comments_desc": "OFFの場合、最新2件のコメント以外が省略されます。",
       "select_search_scope_children_as_default": "検索範囲のデフォルト設定を「この階層下の子ページ」にする",
       "select_search_scope_children_as_default": "検索範囲のデフォルト設定を「この階層下の子ページ」にする",
-      "select_search_scope_children_as_default_desc": "OFFの場合、検索範囲のデフォルト設定は「全てのページ」になります。",
+      "select_search_scope_children_as_default_desc": "OFFの場合、検索範囲のデフォルト設定は「全てのページ」になります。"
+
+    },
+    "presentation":"プレゼンテーション",
+    "presentation_options":{
       "enable_marp": "Marp を有効化する",
       "enable_marp": "Marp を有効化する",
       "enable_marp_desc": "プレゼンテーション表示に Marp を利用できるようになります。ただし、XSS に対して脆弱になる恐れがあります。",
       "enable_marp_desc": "プレゼンテーション表示に Marp を利用できるようになります。ただし、XSS に対して脆弱になる恐れがあります。",
       "marp_official_site": "参考:Marp 公式サイト",
       "marp_official_site": "参考:Marp 公式サイト",
@@ -507,6 +511,7 @@
     "write_css": " システム全体に適用されるCSSを記述できます。",
     "write_css": " システム全体に適用されるCSSを記述できます。",
     "ctrl_space": "Ctrl+Space でコード補完",
     "ctrl_space": "Ctrl+Space でコード補完",
     "custom_script": "カスタムスクリプト",
     "custom_script": "カスタムスクリプト",
+    "custom_presentation":"プレゼンテーション",
     "write_java": "システム全体に適用されるJavaScriptを記述できます。",
     "write_java": "システム全体に適用されるJavaScriptを記述できます。",
     "reflect_change": "変更の反映はページの更新が必要です。",
     "reflect_change": "変更の反映はページの更新が必要です。",
     "custom_logo": "カスタムロゴ",
     "custom_logo": "カスタムロゴ",
@@ -515,7 +520,7 @@
     "current_logo": "現在のロゴ",
     "current_logo": "現在のロゴ",
     "upload_new_logo": "新しいロゴをアップロードする",
     "upload_new_logo": "新しいロゴをアップロードする",
     "delete_logo": "ロゴを削除"
     "delete_logo": "ロゴを削除"
-  },
+   },
   "importer_management": {
   "importer_management": {
     "import_data": "データインポート",
     "import_data": "データインポート",
     "article": "記事",
     "article": "記事",

+ 1 - 0
apps/app/public/static/locales/ja_JP/translation.json

@@ -62,6 +62,7 @@
   "No users have liked this yet": "いいねをしているユーザーはいません",
   "No users have liked this yet": "いいねをしているユーザーはいません",
   "No users have bookmarked yet": "ブックマークしているユーザーはいません",
   "No users have bookmarked yet": "ブックマークしているユーザーはいません",
   "Create Archive Page": "アーカイブページの作成",
   "Create Archive Page": "アーカイブページの作成",
+  "Create Sidebar Page": "<strong>/Sidebar</strong> ページを作成する",
   "Target page": "対象ページ",
   "Target page": "対象ページ",
   "File type": "ファイル形式",
   "File type": "ファイル形式",
   "Include Attachment File": "添付ファイルも含める",
   "Include Attachment File": "添付ファイルも含める",

+ 5 - 1
apps/app/public/static/locales/zh_CN/admin.json

@@ -488,7 +488,10 @@
       "show_all_reply_comments": "显示所有回复评论",
       "show_all_reply_comments": "显示所有回复评论",
       "show_all_reply_comments_desc": "当设置值为“关”时,将忽略最近两个之外的注释。",
       "show_all_reply_comments_desc": "当设置值为“关”时,将忽略最近两个之外的注释。",
       "select_search_scope_children_as_default": "选择“当前分支以下内容”, 作为搜索范围的默认值",
       "select_search_scope_children_as_default": "选择“当前分支以下内容”, 作为搜索范围的默认值",
-      "select_search_scope_children_as_default_desc": "当设置值为“关”时,“所有页面”被作为搜索范围的默认值。",
+      "select_search_scope_children_as_default_desc": "当设置值为“关”时,“所有页面”被作为搜索范围的默认值。"
+    },
+      "presentation": "表达",
+      "presentation_options": {
       "enable_marp": "启用 Marp",
       "enable_marp": "启用 Marp",
       "enable_marp_desc": "Marp 可在演示视图中使用。该选项可能会使您受到 XSS 的攻击。",
       "enable_marp_desc": "Marp 可在演示视图中使用。该选项可能会使您受到 XSS 的攻击。",
       "marp_official_site": "参考资料:Marp 官方网站",
       "marp_official_site": "参考资料:Marp 官方网站",
@@ -507,6 +510,7 @@
     "write_css": "您可以编写应用于整个系统的CSS。",
     "write_css": "您可以编写应用于整个系统的CSS。",
     "ctrl_space": "Ctrl+Space 自动完成",
     "ctrl_space": "Ctrl+Space 自动完成",
     "custom_script": "定制纸条",
     "custom_script": "定制纸条",
+    "custom_presentation":"表达",
     "write_java": "您可以编写应用于整个系统的Javascript。",
     "write_java": "您可以编写应用于整个系统的Javascript。",
     "reflect_change": "您需要重新加载页面以反映更改。",
     "reflect_change": "您需要重新加载页面以反映更改。",
     "custom_logo": "自定义徽标",
     "custom_logo": "自定义徽标",

+ 1 - 0
apps/app/public/static/locales/zh_CN/translation.json

@@ -62,6 +62,7 @@
   "No users have liked this yet": "还没有用户喜欢这个",
   "No users have liked this yet": "还没有用户喜欢这个",
   "No users have bookmarked yet": "还没有用户加入书签",
   "No users have bookmarked yet": "还没有用户加入书签",
   "Create Archive Page": "创建归档页",
   "Create Archive Page": "创建归档页",
+  "Create Sidebar Page": "创建 <strong>/Sidebar</strong> 页面",
   "File type": "文件类型",
   "File type": "文件类型",
   "Target page": "目标页面",
   "Target page": "目标页面",
   "Include Attachment File": "包含附件",
   "Include Attachment File": "包含附件",

+ 21 - 2
apps/app/src/client/services/AdminCustomizeContainer.js

@@ -1,3 +1,4 @@
+/* eslint-disable lines-between-class-members */
 import { isServer } from '@growi/core/dist/utils';
 import { isServer } from '@growi/core/dist/utils';
 import { Container } from 'unstated';
 import { Container } from 'unstated';
 
 
@@ -154,7 +155,7 @@ export default class AdminCustomizeContainer extends Container {
   /**
   /**
    * Switch isEnabledMarp
    * Switch isEnabledMarp
    */
    */
-  switchIsEnabledMarp() {
+  switchIsEnabledMarp(inputValue) {
     this.setState({ isEnabledMarp: !this.state.isEnabledMarp });
     this.setState({ isEnabledMarp: !this.state.isEnabledMarp });
   }
   }
 
 
@@ -203,7 +204,6 @@ export default class AdminCustomizeContainer extends Container {
         isEnabledStaleNotification: this.state.isEnabledStaleNotification,
         isEnabledStaleNotification: this.state.isEnabledStaleNotification,
         isAllReplyShown: this.state.isAllReplyShown,
         isAllReplyShown: this.state.isAllReplyShown,
         isSearchScopeChildrenAsDefault: this.state.isSearchScopeChildrenAsDefault,
         isSearchScopeChildrenAsDefault: this.state.isSearchScopeChildrenAsDefault,
-        isEnabledMarp: this.state.isEnabledMarp,
       });
       });
       const { customizedParams } = response.data;
       const { customizedParams } = response.data;
       this.setState({
       this.setState({
@@ -216,6 +216,25 @@ export default class AdminCustomizeContainer extends Container {
         isEnabledStaleNotification: customizedParams.isEnabledStaleNotification,
         isEnabledStaleNotification: customizedParams.isEnabledStaleNotification,
         isAllReplyShown: customizedParams.isAllReplyShown,
         isAllReplyShown: customizedParams.isAllReplyShown,
         isSearchScopeChildrenAsDefault: customizedParams.isSearchScopeChildrenAsDefault,
         isSearchScopeChildrenAsDefault: customizedParams.isSearchScopeChildrenAsDefault,
+      });
+    }
+    catch (err) {
+      logger.error(err);
+      throw new Error('Failed to update data');
+    }
+  }
+  /**
+   * Update presentation
+   * @memberOf AdminCustomizeContainer
+   */
+  async updateCustomizePresentation() {
+    try {
+      const response = await apiv3Put('/customize-setting/presentation', {
+        isEnabledMarp: this.state.isEnabledMarp,
+      });
+
+      const { customizedParams } = response.data;
+      this.setState({
         isEnabledMarp: customizedParams.isEnabledMarp,
         isEnabledMarp: customizedParams.isEnabledMarp,
       });
       });
     }
     }

+ 4 - 0
apps/app/src/components/Admin/Customize/Customize.jsx

@@ -15,6 +15,7 @@ import CustomizeFunctionSetting from './CustomizeFunctionSetting';
 import CustomizeLayoutSetting from './CustomizeLayoutSetting';
 import CustomizeLayoutSetting from './CustomizeLayoutSetting';
 import CustomizeLogoSetting from './CustomizeLogoSetting';
 import CustomizeLogoSetting from './CustomizeLogoSetting';
 import CustomizeNoscriptSetting from './CustomizeNoscriptSetting';
 import CustomizeNoscriptSetting from './CustomizeNoscriptSetting';
+import CustomizePresentationSetting from './CustomizePresentationSetting';
 import CustomizeScriptSetting from './CustomizeScriptSetting';
 import CustomizeScriptSetting from './CustomizeScriptSetting';
 import CustomizeSidebarSetting from './CustomizeSidebarSetting';
 import CustomizeSidebarSetting from './CustomizeSidebarSetting';
 import CustomizeThemeSetting from './CustomizeThemeSetting';
 import CustomizeThemeSetting from './CustomizeThemeSetting';
@@ -58,6 +59,9 @@ function Customize(props) {
       <div className="mb-5">
       <div className="mb-5">
         <CustomizeFunctionSetting />
         <CustomizeFunctionSetting />
       </div>
       </div>
+      <div className="mb-5">
+        <CustomizePresentationSetting />
+      </div>
       <div className="mb-5">
       <div className="mb-5">
         <CustomizeTitle />
         <CustomizeTitle />
       </div>
       </div>

+ 0 - 28
apps/app/src/components/Admin/Customize/CustomizeFunctionSetting.tsx

@@ -133,34 +133,6 @@ const CustomizeFunctionSetting = (props: Props): JSX.Element => {
             </div>
             </div>
           </div>
           </div>
 
 
-          <div className="form-group row">
-            <div className="offset-md-3 col-md-6 text-left">
-              <CustomizeFunctionOption
-                optionId="isEnabledMarp"
-                label={t('admin:customize_settings.function_options.enable_marp')}
-                isChecked={adminCustomizeContainer.state.isEnabledMarp || false}
-                onChecked={() => { adminCustomizeContainer.switchIsEnabledMarp() }}
-              >
-                <p className="form-text text-muted">
-                  {t('admin:customize_settings.function_options.enable_marp_desc')}
-                  <br></br>
-                  <a
-                    href={`${t('admin:customize_settings.function_options.marp_official_site_link')}`}
-                    target="_blank"
-                    rel="noopener noreferrer"
-                  >{`${t('admin:customize_settings.function_options.marp_official_site')}`}
-                  </a>
-                  <br></br>
-                  <a
-                    href={`${t('admin:customize_settings.function_options.marp_in_growi_link')}`}
-                    target="_blank"
-                    rel="noopener noreferrer"
-                  >{`${t('admin:customize_settings.function_options.marp_in_growi')}`}
-                  </a>
-                </p>
-              </CustomizeFunctionOption>
-            </div>
-          </div>
 
 
           <AdminUpdateButtonRow onClick={onClickSubmit} disabled={adminCustomizeContainer.state.retrieveError != null} />
           <AdminUpdateButtonRow onClick={onClickSubmit} disabled={adminCustomizeContainer.state.retrieveError != null} />
         </div>
         </div>

+ 70 - 0
apps/app/src/components/Admin/Customize/CustomizePresentationSetting.tsx

@@ -0,0 +1,70 @@
+import React, { useCallback } from 'react';
+
+import { useTranslation } from 'next-i18next';
+
+import AdminCustomizeContainer from '~/client/services/AdminCustomizeContainer';
+import { toastSuccess, toastError } from '~/client/util/toastr';
+
+import { withUnstatedContainers } from '../../UnstatedUtils';
+import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
+
+import CustomizePresentationOption from './CustomizeFunctionOption';
+
+type Props = {
+  adminCustomizeContainer: AdminCustomizeContainer
+}
+
+const CustomizePresentationSetting = (props: Props): JSX.Element => {
+  const { adminCustomizeContainer } = props;
+
+  console.log(adminCustomizeContainer);
+
+  const { t } = useTranslation();
+  const onClickSubmit = useCallback(async() => {
+    try {
+      await adminCustomizeContainer.updateCustomizePresentation();
+      toastSuccess(t('toaster.update_successed', { target: t('admin:customize_settings.presentation'), ns: 'commons' }));
+    }
+    catch (err) {
+      toastError(err);
+    }
+  }, [adminCustomizeContainer]);
+  return (
+    <React.Fragment>
+      <h2 className="admin-setting-header">{t('admin:customize_settings.custom_presentation')}</h2>
+      <div className="form-group row">
+        <div className="offset-md-3 col-md-6 text-left">
+          <CustomizePresentationOption
+            optionId="isEnabledMarp"
+            label={t('admin:customize_settings.presentation_options.enable_marp')}
+            isChecked={adminCustomizeContainer?.state.isEnabledMarp || false}
+            onChecked={() => { adminCustomizeContainer.switchIsEnabledMarp() }}
+          >
+            <p className="form-text text-muted">
+              {t('admin:customize_settings.presentation_options.enable_marp_desc')}
+              <br></br>
+              <a
+                href={`${t('admin:customize_settings.presentation_options.marp_official_site_link')}`}
+                target="_blank"
+                rel="noopener noreferrer"
+              >{`${t('admin:customize_settings.presentation_options.marp_official_site')}`}
+              </a>
+              <br></br>
+              <a
+                href={`${t('admin:customize_settings.presentation_options.marp_in_gorwi_link')}`}
+                target="_blank"
+                rel="noopener noreferrer"
+              >{`${t('admin:customize_settings.presenattion_options.marp_in_growi')}`}
+              </a>
+            </p>
+          </CustomizePresentationOption>
+        </div>
+      </div>
+
+      <AdminUpdateButtonRow onClick={onClickSubmit} disabled={adminCustomizeContainer.state.retrieveError != null} />
+    </React.Fragment>
+  );
+};
+const CustomizePresentationSettingWrapper = withUnstatedContainers(CustomizePresentationSetting, [AdminCustomizeContainer]);
+
+export default CustomizePresentationSettingWrapper;

+ 1 - 2
apps/app/src/components/Bookmarks/BookmarkFolderItem.tsx

@@ -10,7 +10,6 @@ import {
 } from '~/client/util/bookmark-utils';
 } from '~/client/util/bookmark-utils';
 import { toastError } from '~/client/util/toastr';
 import { toastError } from '~/client/util/toastr';
 import { FolderIcon } from '~/components/Icons/FolderIcon';
 import { FolderIcon } from '~/components/Icons/FolderIcon';
-import { TriangleIcon } from '~/components/Icons/TriangleIcon';
 import {
 import {
   BookmarkFolderItems, DragItemDataType, DragItemType, DRAG_ITEM_TYPE,
   BookmarkFolderItems, DragItemDataType, DragItemType, DRAG_ITEM_TYPE,
 } from '~/interfaces/bookmark-info';
 } from '~/interfaces/bookmark-info';
@@ -234,7 +233,7 @@ export const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkF
                 onClick={loadChildFolder}
                 onClick={loadChildFolder}
               >
               >
                 <div className="d-flex justify-content-center">
                 <div className="d-flex justify-content-center">
-                  <TriangleIcon />
+                  <span className="material-icons-round">arrow_right</span>
                 </div>
                 </div>
               </button>
               </button>
             )}
             )}

+ 4 - 2
apps/app/src/components/Bookmarks/BookmarkFolderTree.module.scss

@@ -40,7 +40,7 @@ $grw-bookmark-item-padding-left: 35px;
     }
     }
 
 
     .grw-foldertree-triangle-btn {
     .grw-foldertree-triangle-btn {
-      background-color: transparent;
+      border: 0;
       transition: all 0.2s ease-out;
       transition: all 0.2s ease-out;
       transform: rotate(0deg);
       transform: rotate(0deg);
 
 
@@ -58,7 +58,9 @@ $grw-bookmark-item-padding-left: 35px;
 
 
   .grw-foldertree-item-container {
   .grw-foldertree-item-container {
     .grw-triangle-container {
     .grw-triangle-container {
-      min-width: 35px;
+      // TODO: ignore width frickering
+      // https://redmine.weseek.co.jp/issues/130828
+      // min-width: 35px;
       height: 40px;
       height: 40px;
     }
     }
 
 

+ 0 - 15
apps/app/src/components/Icons/TriangleIcon.tsx

@@ -1,15 +0,0 @@
-import React from 'react';
-
-export const TriangleIcon = (): JSX.Element => (
-  <svg
-    xmlns="http://www.w3.org/2000/svg"
-    width="12"
-    height="12"
-    viewBox="0 0 12 12"
-  >
-    <g transform="translate(18194 -6790)">
-      <rect width="12" height="12" transform="translate(-18194 6790)" fill="none" />
-      <path d="M5.2,1.067a1,1,0,0,1,1.6,0l4,5.333A1,1,0,0,1,10,8H2a1,1,0,0,1-.8-1.6Z" transform="translate(-18183 6790) rotate(90)" />
-    </g>
-  </svg>
-);

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

@@ -83,7 +83,7 @@ export const InAppNotificationDropdown = (): JSX.Element => {
 
 
   return (
   return (
     <Dropdown className="notification-wrapper grw-notification-dropdown" isOpen={isOpen} toggle={toggleDropdownHandler} direction="end">
     <Dropdown className="notification-wrapper grw-notification-dropdown" isOpen={isOpen} toggle={toggleDropdownHandler} direction="end">
-      <DropdownToggle className="px-3 nav-link border-0 bg-transparent" innerRef={buttonRef}>
+      <DropdownToggle className="px-3" color="primary" innerRef={buttonRef}>
         <i className="icon-bell" /> {badge}
         <i className="icon-bell" /> {badge}
       </DropdownToggle>
       </DropdownToggle>
       <DropdownMenu end>
       <DropdownMenu end>

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

@@ -21,7 +21,6 @@
     width: 3rem;
     width: 3rem;
     height: 3rem;
     height: 3rem;
     font-size: 1.5rem;
     font-size: 1.5rem;
-    color: var(--color-global);
     opacity: 0.3;
     opacity: 0.3;
   }
   }
 
 

+ 3 - 2
apps/app/src/components/Sidebar/Custom/CustomSidebar.tsx

@@ -1,5 +1,6 @@
 import { Suspense } from 'react';
 import { Suspense } from 'react';
 
 
+import dynamic from 'next/dynamic';
 import Link from 'next/link';
 import Link from 'next/link';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
 
 
@@ -8,8 +9,8 @@ import { useSWRxPageByPath } from '~/stores/page';
 import { SidebarHeaderReloadButton } from '../SidebarHeaderReloadButton';
 import { SidebarHeaderReloadButton } from '../SidebarHeaderReloadButton';
 import DefaultContentSkeleton from '../Skeleton/DefaultContentSkeleton';
 import DefaultContentSkeleton from '../Skeleton/DefaultContentSkeleton';
 
 
-import { CustomSidebarSubstance } from './CustomSidebarSubstance';
 
 
+const CustomSidebarContent = dynamic(() => import('./CustomSidebarSubstance').then(mod => mod.CustomSidebarSubstance), { ssr: false });
 
 
 export const CustomSidebar = (): JSX.Element => {
 export const CustomSidebar = (): JSX.Element => {
   const { t } = useTranslation();
   const { t } = useTranslation();
@@ -27,7 +28,7 @@ export const CustomSidebar = (): JSX.Element => {
       </div>
       </div>
 
 
       <Suspense fallback={<DefaultContentSkeleton />}>
       <Suspense fallback={<DefaultContentSkeleton />}>
-        <CustomSidebarSubstance />
+        <CustomSidebarContent />
       </Suspense>
       </Suspense>
     </div>
     </div>
   );
   );

+ 6 - 1
apps/app/src/components/Sidebar/Custom/CustomSidebarNotFound.tsx

@@ -1,10 +1,15 @@
 import Link from 'next/link';
 import Link from 'next/link';
+import { useTranslation } from 'react-i18next';
 
 
 export const SidebarNotFound = (): JSX.Element => {
 export const SidebarNotFound = (): JSX.Element => {
+  const { t } = useTranslation();
+
   return (
   return (
     <div className="grw-sidebar-content-header h5 text-center py-3">
     <div className="grw-sidebar-content-header h5 text-center py-3">
       <Link href="/Sidebar#edit">
       <Link href="/Sidebar#edit">
-        <i className="icon-magic-wand"></i>Create<strong>/Sidebar</strong>page
+        <i className="icon-fw icon-magic-wand"></i>
+        {/* eslint-disable-next-line react/no-danger */}
+        <span dangerouslySetInnerHTML={{ __html: t('Create Sidebar Page') }}></span>
       </Link>
       </Link>
     </div>
     </div>
   );
   );

+ 1 - 1
apps/app/src/components/Sidebar/Custom/CustomSidebarSubstance.tsx

@@ -23,7 +23,7 @@ export const CustomSidebarSubstance = (): JSX.Element => {
 
 
   return (
   return (
     <div className={`py-3 grw-custom-sidebar-content ${styles['grw-custom-sidebar-content']}`}>
     <div className={`py-3 grw-custom-sidebar-content ${styles['grw-custom-sidebar-content']}`}>
-      { markdown === undefined
+      { markdown == null
         ? <SidebarNotFound />
         ? <SidebarNotFound />
         : (
         : (
           <RevisionRenderer
           <RevisionRenderer

+ 37 - 0
apps/app/src/components/Sidebar/PageTree/Item.module.scss

@@ -0,0 +1,37 @@
+@use '@growi/core/scss/bootstrap/init' as bs;
+
+// TODO: relocate following styles into PageTreeItem.mdoule.scss after refactoring
+// https://redmine.weseek.co.jp/issues/127544
+.pagetree-item :global {
+  .list-group-item {
+    --bs-list-group-bg: transparent;
+  }
+}
+@include bs.color-mode(light) {
+  .pagetree-item :global {
+    .list-group-item-action {
+      --bs-list-group-action-hover-bg: var(--grw-highlight-200);
+      --bs-list-group-action-active-bg: var(--grw-highlight-400);
+
+      .btn-page-item-control {
+        --bs-btn-bg: transparent;
+        --bs-btn-hover-bg: var(--grw-highlight-400);
+        --bs-btn-active-bg: var(--grw-highlight-600);
+      }
+    }
+  }
+}
+@include bs.color-mode(dark) {
+  .pagetree-item :global {
+    .list-group-item-action {
+      --bs-list-group-action-hover-bg: var(--grw-highlight-800);
+      --bs-list-group-action-active-bg: var(--grw-highlight-800);
+
+      .btn-page-item-control {
+        --bs-btn-bg: transparent;
+        --bs-btn-hover-bg: var(--grw-highlight-700);
+        --bs-btn-active-bg: var(--grw-highlight-800);
+      }
+    }
+  }
+}

+ 7 - 3
apps/app/src/components/Sidebar/PageTree/Item.tsx

@@ -20,7 +20,6 @@ import { bookmark, unbookmark, resumeRenameOperation } from '~/client/services/p
 import { apiv3Put, apiv3Post } from '~/client/util/apiv3-client';
 import { apiv3Put, apiv3Post } from '~/client/util/apiv3-client';
 import { ValidationTarget } from '~/client/util/input-validator';
 import { ValidationTarget } from '~/client/util/input-validator';
 import { toastWarning, toastError, toastSuccess } from '~/client/util/toastr';
 import { toastWarning, toastError, toastSuccess } from '~/client/util/toastr';
-import { TriangleIcon } from '~/components/Icons/TriangleIcon';
 import { NotAvailableForGuest } from '~/components/NotAvailableForGuest';
 import { NotAvailableForGuest } from '~/components/NotAvailableForGuest';
 import { NotAvailableForReadOnlyUser } from '~/components/NotAvailableForReadOnlyUser';
 import { NotAvailableForReadOnlyUser } from '~/components/NotAvailableForReadOnlyUser';
 import { useSWRMUTxCurrentUserBookmarks } from '~/stores/bookmark';
 import { useSWRMUTxCurrentUserBookmarks } from '~/stores/bookmark';
@@ -38,6 +37,9 @@ import { PageItemControl } from '../../Common/Dropdown/PageItemControl';
 import { ItemNode } from './ItemNode';
 import { ItemNode } from './ItemNode';
 
 
 
 
+import styles from './Item.module.scss';
+
+
 const logger = loggerFactory('growi:cli:Item');
 const logger = loggerFactory('growi:cli:Item');
 
 
 
 
@@ -424,7 +426,9 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
       id={`pagetree-item-${page._id}`}
       id={`pagetree-item-${page._id}`}
       data-testid="grw-pagetree-item-container"
       data-testid="grw-pagetree-item-container"
       className={`grw-pagetree-item-container ${isOver ? 'grw-pagetree-is-over' : ''}
       className={`grw-pagetree-item-container ${isOver ? 'grw-pagetree-is-over' : ''}
-    ${shouldHide ? 'd-none' : ''}`}
+        pagetree-item ${styles['pagetree-item']}
+        ${shouldHide ? 'd-none' : ''}`
+      }
     >
     >
       <li
       <li
         ref={(c) => { drag(c); drop(c) }}
         ref={(c) => { drag(c); drop(c) }}
@@ -440,7 +444,7 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
               onClick={onClickLoadChildren}
               onClick={onClickLoadChildren}
             >
             >
               <div className="d-flex justify-content-center">
               <div className="d-flex justify-content-center">
-                <TriangleIcon />
+                <span className="material-icons-round">arrow_right</span>
               </div>
               </div>
             </button>
             </button>
           )}
           )}

+ 11 - 2
apps/app/src/components/Sidebar/PageTree/ItemsTree.module.scss

@@ -41,7 +41,7 @@ $grw-pagetree-item-container-height: 40px;
       }
       }
 
 
       .grw-pagetree-triangle-btn {
       .grw-pagetree-triangle-btn {
-        background-color: transparent;
+        border: 0;
         transition: all 0.2s ease-out;
         transition: all 0.2s ease-out;
         transform: rotate(0deg);
         transform: rotate(0deg);
 
 
@@ -67,7 +67,9 @@ $grw-pagetree-item-container-height: 40px;
 
 
     .grw-pagetree-item-container {
     .grw-pagetree-item-container {
       .grw-triangle-container {
       .grw-triangle-container {
-        min-width: 35px;
+        // TODO: ignore width frickering
+        // https://redmine.weseek.co.jp/issues/130828
+        // min-width: 35px;
         height: $grw-pagetree-item-container-height;
         height: $grw-pagetree-item-container-height;
       }
       }
     }
     }
@@ -151,3 +153,10 @@ $grw-pagetree-item-container-height: 40px;
     }
     }
   }
   }
 }
 }
+
+
+.grw-pagetree :global {
+  .grw-pagetree-triangle-btn {
+    --btn-color: var(--bs-tertiary-color);
+  }
+}

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

@@ -49,59 +49,59 @@ export const PersonalDropdown = (): JSX.Element => {
           data-testid="personal-dropdown-button"
           data-testid="personal-dropdown-button"
           aria-expanded="false"
           aria-expanded="false"
         >
         >
-          <UserPicture user={currentUser} noLink noTooltip /><span className="ms-1 d-none d-lg-inline-block">&nbsp;{currentUser.name}</span>
+          <UserPicture user={currentUser} noLink noTooltip />
         </button>
         </button>
 
 
         {/* Menu */}
         {/* Menu */}
-        <div className="dropdown-menu" data-testid="personal-dropdown-menu">
-
-          <div className="px-4 pt-3 pb-2 text-center">
+        <ul className="dropdown-menu" data-testid="personal-dropdown-menu">
+          <li className="px-4 pt-3 pb-2">
             <UserPicture user={currentUser} size="lg" noLink noTooltip />
             <UserPicture user={currentUser} size="lg" noLink noTooltip />
-
-            <h5 className="mt-2">
-              {currentUser.name}
-            </h5>
-
-            <div className="my-2">
-              <i className="icon-user icon-fw"></i>{currentUser.username}<br />
-              <i className="icon-envelope icon-fw"></i><span className="grw-email-sm">{currentUser.email}</span>
+            <h5>{currentUser.name}</h5>
+            <div className="d-flex align-items-center">
+              <i className="icon-user icon-fw"></i>{currentUser.username}
             </div>
             </div>
-
-            <div className="btn-group mt-2" role="group">
-              <Link
-                href={pagePathUtils.userHomepagePath(currentUser)}
-                className="btn btn-sm btn-outline-secondary col"
-                data-testid="grw-personal-dropdown-menu-user-home"
-              >
-                <i className="icon-fw icon-home"></i>{t('personal_dropdown.home')}
-              </Link>
-              <Link
-                href="/me"
-                className="btn btn-sm btn-outline-secondary col"
-                data-testid="grw-personal-dropdown-menu-user-settings"
-              >
-                <i className="icon-fw icon-wrench"></i>{t('personal_dropdown.settings')}
-              </Link>
+            <div className="d-flex align-items-center">
+              <i className="icon-envelope icon-fw"></i><span className="grw-email-sm">{currentUser.email}</span>
             </div>
             </div>
-          </div>
-
-          <div className="dropdown-divider"></div>
-
-          <button
-            data-testid="grw-proactive-questionnaire-modal-toggle-btn"
-            type="button"
-            className="dropdown-item"
-            onClick={() => setQuestionnaireModalOpen(true)}
-          >
-            <i className="icon-fw icon-pencil"></i>{t('personal_dropdown.feedback')}
-          </button>
-
-          <div className="dropdown-divider"></div>
+          </li>
+
+          <li className="dropdown-divider"></li>
+
+          <li>
+            <Link
+              href={pagePathUtils.userHomepagePath(currentUser)}
+              className="dropdown-item"
+              data-testid="grw-personal-dropdown-menu-user-home"
+            >
+              <i className="icon-fw icon-home"></i>{t('personal_dropdown.home')}
+            </Link>
+          </li>
+          <li>
+            <Link
+              href="/me"
+              className="dropdown-item"
+              data-testid="grw-personal-dropdown-menu-user-settings"
+            >
+              <i className="icon-fw icon-wrench"></i>{t('personal_dropdown.settings')}
+            </Link>
+          </li>
+          <li>
+            <button
+              data-testid="grw-proactive-questionnaire-modal-toggle-btn"
+              type="button"
+              className="dropdown-item"
+              onClick={() => setQuestionnaireModalOpen(true)}
+            >
+              <i className="icon-fw icon-pencil"></i>{t('personal_dropdown.feedback')}
+            </button>
+          </li>
+          <li>
+            <button type="button" className="dropdown-item" onClick={logoutHandler}>
+              <i className="icon-fw icon-power"></i>{t('Sign out')}
+            </button>
+          </li>
+        </ul>
 
 
-          <button type="button" className="dropdown-item" onClick={logoutHandler}>
-            <i className="icon-fw icon-power"></i>{t('Sign out')}
-          </button>
-        </div>
       </div>
       </div>
 
 
       <ProactiveQuestionnaireModal isOpen={isQuestionnaireModalOpen} onClose={() => setQuestionnaireModalOpen(false)} />
       <ProactiveQuestionnaireModal isOpen={isQuestionnaireModalOpen} onClose={() => setQuestionnaireModalOpen(false)} />

+ 33 - 5
apps/app/src/components/Sidebar/Sidebar.module.scss

@@ -9,17 +9,13 @@
   // set the max value that should be taken when sticky
   // set the max value that should be taken when sticky
   height: 100vh;
   height: 100vh;
 
 
+  border-right : 1px solid var(--bs-border-color);
 
 
   .data-layout-container {
   .data-layout-container {
     display: flex;
     display: flex;
     flex-direction: row;
     flex-direction: row;
     height: 100vh;
     height: 100vh;
     margin-top: 0px;
     margin-top: 0px;
-    // css-teprsg
-    > div:nth-of-type(2) {
-      padding-left: unset !important;
-      margin-left: unset !important;
-    }
   }
   }
   .navigation {
   .navigation {
     .grw-navigation-wrap {
     .grw-navigation-wrap {
@@ -218,3 +214,35 @@
     }
     }
   }
   }
 }
 }
+
+
+.grw-sidebar :global {
+  .grw-contextual-navigation {
+    --bs-heading-color: var(--bs-tertiary-color);
+    --bs-body-color: var(--bs-secondary-color);
+    --bs-link-color-rgb: var(--bs-secondary-color-rgb);
+    --bs-link-opacity: .75;
+
+    backdrop-filter: blur(20px);
+  }
+}
+@include bs.color-mode(light) {
+  .grw-sidebar :global {
+    --bs-border-color: var(--grw-highlight-200);
+
+    .grw-contextual-navigation {
+      background-color: rgba(var(--grw-highlight-100-rgb), .5);
+    }
+  }
+}
+
+@include bs.color-mode(dark) {
+  .grw-sidebar :global {
+    --bs-color: var(--bs-gray-400);
+    --bs-border-color: var(--grw-highlight-800);
+
+    .grw-contextual-navigation {
+      background-color: rgba(var(--grw-highlight-900-rgb), .5);
+    }
+  }
+}

+ 68 - 29
apps/app/src/components/Sidebar/SidebarNav.module.scss

@@ -3,31 +3,14 @@
 @use '~/styles/variables' as var;
 @use '~/styles/variables' as var;
 
 
 .grw-sidebar-nav :global {
 .grw-sidebar-nav :global {
-  $sidebar-nav-button-height: 55px;
-
-  %fukidashi-for-active {
-    position: relative;
-
-    // speech balloon
-    &:after {
-      position: absolute;
-      right: -0.1em;
-      display: block;
-      width: 0;
-      content: '';
-      border: 9px solid transparent;
-      border-right-color: white;
-      border-left-width: 0;
-      transform: translateY(-#{$sidebar-nav-button-height / 2});
-    }
-  }
-
   // set position and z-index to prevent dropdowns covered by other element
   // set position and z-index to prevent dropdowns covered by other element
   position: relative;
   position: relative;
   z-index: bs.$zindex-fixed;
   z-index: bs.$zindex-fixed;
 
 
   height: 100vh;
   height: 100vh;
 
 
+  border-right : 1px solid var(--bs-border-color);
+
   .grw-logo {
   .grw-logo {
     svg {
     svg {
       width: var.$grw-logo-width;
       width: var.$grw-logo-width;
@@ -50,33 +33,47 @@
 
 
   .btn {
   .btn {
     width: var.$grw-sidebar-nav-width;
     width: var.$grw-sidebar-nav-width;
+    height: var.$grw-sidebar-nav-height;
+    padding-top: .75rem;
+    padding-bottom: .75rem;
     line-height: 1em;
     line-height: 1em;
+    border: 0;
     border-radius: 0;
     border-radius: 0;
     box-shadow: none !important;
     box-shadow: none !important;
 
 
     // icon opacity
     // icon opacity
     &:not(.active) {
     &:not(.active) {
       i {
       i {
-        opacity: 0.4;
+        opacity: 0.7;
       }
       }
       &:hover,
       &:hover,
       &:focus {
       &:focus {
         i {
         i {
-          opacity: 0.7;
+          opacity: 0.8;
         }
         }
       }
       }
     }
     }
   }
   }
 
 
   .grw-sidebar-nav-primary-container {
   .grw-sidebar-nav-primary-container {
-    .btn {
-      padding: 1em;
-      i {
-        font-size: 2.3em;
-      }
+    $btn-active-indicator-height: 34px;
 
 
+    .btn {
       &.active {
       &.active {
-        @extend %fukidashi-for-active;
+        position: relative;
+
+        // indicator
+        &:after {
+          position: absolute;
+          top: 0;
+          left: 0;
+          display: block;
+          width: 3px;
+          height: $btn-active-indicator-height;
+          content: '';
+          background-color: var(--bs-primary);
+          transform: translateY(#{(var.$grw-sidebar-nav-height - $btn-active-indicator-height) / 2});
+        }
       }
       }
     }
     }
   }
   }
@@ -86,10 +83,52 @@
     bottom: 1.5rem;
     bottom: 1.5rem;
 
 
     .btn {
     .btn {
-      padding: 0.9em;
       i {
       i {
-        font-size: 1.5em;
+        opacity: 0.4;
       }
       }
     }
     }
   }
   }
 }
 }
+
+
+// == Colors
+.grw-sidebar-nav :global {
+  .btn.btn-primary {
+    --bs-btn-bg: transparent;
+    --bs-btn-active-bg: transparent;
+    --bs-btn-hover-color: var(
+      --grw-sidebar-nav-btn-hover-color,
+      var(
+        --grw-sidebar-nav-btn-color,
+        var(--bs-btn-color)
+      ),
+    );
+    --bs-btn-active-color: var(
+      --grw-sidebar-nav-btn-active-color,
+      var(
+        --grw-sidebar-nav-btn-color,
+        var(--bs-btn-color)
+      ),
+    );
+  }
+}
+@include bs.color-mode(light) {
+  .grw-sidebar-nav :global {
+    background-color: var(--grw-sidebar-nav-bg, var(--grw-highlight-100));
+
+    .btn-primary {
+      --bs-btn-color: var(--grw-sidebar-nav-btn-color, var(--grw-primary-500));
+      --bs-btn-hover-bg: var(--grw-sidebar-nav-btn-hover-bg, var(--grw-highlight-300));
+    }
+  }
+}
+@include bs.color-mode(dark) {
+  .grw-sidebar-nav :global {
+    background-color: var(--grw-sidebar-nav-bg, var(--grw-highlight-900));
+
+    .btn-primary {
+      --bs-btn-color: var(--grw-sidebar-nav-btn-color, var(--grw-primary-400));
+      --bs-btn-hover-bg: var(--grw-sidebar-nav-btn-hover-bg, var(--grw-highlight-700));
+    }
+  }
+}

+ 6 - 12
apps/app/src/components/Sidebar/SidebarNav.tsx

@@ -115,26 +115,20 @@ export const SidebarNav: FC<Props> = (props: Props) => {
       </div>
       </div>
 
 
       <div className="grw-sidebar-nav-primary-container" data-vrt-blackout-sidebar-nav>
       <div className="grw-sidebar-nav-primary-container" data-vrt-blackout-sidebar-nav>
-        {/* eslint-disable max-len */}
         <PrimaryItem contents={SidebarContentsType.TREE} label="Page Tree" iconName="format_list_bulleted" onItemSelected={onItemSelected} />
         <PrimaryItem contents={SidebarContentsType.TREE} label="Page Tree" iconName="format_list_bulleted" onItemSelected={onItemSelected} />
         <PrimaryItem contents={SidebarContentsType.CUSTOM} label="Custom Sidebar" iconName="code" onItemSelected={onItemSelected} />
         <PrimaryItem contents={SidebarContentsType.CUSTOM} label="Custom Sidebar" iconName="code" onItemSelected={onItemSelected} />
         <PrimaryItem contents={SidebarContentsType.RECENT} label="Recent Changes" iconName="update" onItemSelected={onItemSelected} />
         <PrimaryItem contents={SidebarContentsType.RECENT} label="Recent Changes" iconName="update" onItemSelected={onItemSelected} />
-        {/* <PrimaryItem id="tag" label="Tags" iconName="icon-tag" /> */}
-        {/* <PrimaryItem id="favorite" label="Favorite" iconName="fa fa-bookmark-o" /> */}
-        <PrimaryItem contents={SidebarContentsType.TAG} label="Tags" iconName="local_offer" onItemSelected={onItemSelected} />
-        {/* <PrimaryItem id="favorite" label="Favorite" iconName="icon-star" /> */}
-        {/* eslint-enable max-len */}
         <PrimaryItem contents={SidebarContentsType.BOOKMARKS} label="Bookmarks" iconName="bookmark" onItemSelected={onItemSelected} />
         <PrimaryItem contents={SidebarContentsType.BOOKMARKS} label="Bookmarks" iconName="bookmark" onItemSelected={onItemSelected} />
+        <PrimaryItem contents={SidebarContentsType.TAG} label="Tags" iconName="local_offer" onItemSelected={onItemSelected} />
+        <InAppNotificationDropdown />
       </div>
       </div>
       <div className="grw-sidebar-nav-secondary-container">
       <div className="grw-sidebar-nav-secondary-container">
-        <AppearanceModeDropdown isAuthenticated={isAuthenticated} />
+        {/* TODO: This setting will be consolidated in "Settings" on My Page, so delete it from here. */}
+        {/* <AppearanceModeDropdown isAuthenticated={isAuthenticated} /> */}
         <PersonalDropdown />
         <PersonalDropdown />
-        <InAppNotificationDropdown />
-
-        {isAdmin && <SecondaryItem label="Admin" iconName="settings" href="/admin" />}
-        {/* <SecondaryItem label="Draft" iconName="file_copy" href="/me/drafts" /> */}
         <SecondaryItem label="Help" iconName="help" href={growiCloudUri != null ? 'https://growi.cloud/help/' : 'https://docs.growi.org'} isBlank />
         <SecondaryItem label="Help" iconName="help" href={growiCloudUri != null ? 'https://growi.cloud/help/' : 'https://docs.growi.org'} isBlank />
-        <SecondaryItem label="Trash" iconName="delete" href="/trash" />
+        {isAdmin && <SecondaryItem label="Admin" iconName="settings" href="/admin" />}
+        <SecondaryItem label="Trash" href="/trash" iconName="delete" />
       </div>
       </div>
     </div>
     </div>
   );
   );

+ 0 - 1
apps/app/src/pages/_app.page.tsx

@@ -21,7 +21,6 @@ import { registerTransformerForObjectId } from './utils/objectid-transformer';
 import '~/styles/prebuilt/vendor.css';
 import '~/styles/prebuilt/vendor.css';
 import '~/styles/font-icons.scss';
 import '~/styles/font-icons.scss';
 import '~/styles/style-app.scss';
 import '~/styles/style-app.scss';
-import '~/styles/prebuilt/apply-colors.css';
 
 
 
 
 const isDev = process.env.NODE_ENV === 'development';
 const isDev = process.env.NODE_ENV === 'development';

+ 8 - 1
apps/app/src/server/.node-dev.json

@@ -1,3 +1,10 @@
 {
 {
-  "ignore": ["package.json", ".next", "public/static"]
+  "ignore": [
+    "package.json",
+    ".next",
+    "public/static",
+
+    "// ignore watching preset theme updates",
+    "packages/preset-themes/dist/themes/manifest.json"
+  ]
 }
 }

+ 24 - 4
apps/app/src/server/routes/apiv3/customize-setting.js

@@ -61,8 +61,6 @@ const router = express.Router();
  *            type: boolean
  *            type: boolean
  *          isSearchScopeChildrenAsDefault:
  *          isSearchScopeChildrenAsDefault:
  *            type: boolean
  *            type: boolean
- *          isEnabledMarp:
- *            type: boolean
  *      CustomizeHighlight:
  *      CustomizeHighlight:
  *        description: CustomizeHighlight
  *        description: CustomizeHighlight
  *        type: object
  *        type: object
@@ -127,6 +125,8 @@ module.exports = (crowi) => {
       body('isEnabledStaleNotification').isBoolean(),
       body('isEnabledStaleNotification').isBoolean(),
       body('isAllReplyShown').isBoolean(),
       body('isAllReplyShown').isBoolean(),
       body('isSearchScopeChildrenAsDefault').isBoolean(),
       body('isSearchScopeChildrenAsDefault').isBoolean(),
+    ],
+    CustomizePresentation: [
       body('isEnabledMarp').isBoolean(),
       body('isEnabledMarp').isBoolean(),
     ],
     ],
     customizeTitle: [
     customizeTitle: [
@@ -411,7 +411,6 @@ module.exports = (crowi) => {
       'customize:isEnabledStaleNotification': req.body.isEnabledStaleNotification,
       'customize:isEnabledStaleNotification': req.body.isEnabledStaleNotification,
       'customize:isAllReplyShown': req.body.isAllReplyShown,
       'customize:isAllReplyShown': req.body.isAllReplyShown,
       'customize:isSearchScopeChildrenAsDefault': req.body.isSearchScopeChildrenAsDefault,
       'customize:isSearchScopeChildrenAsDefault': req.body.isSearchScopeChildrenAsDefault,
-      'customize:isEnabledMarp': req.body.isEnabledMarp,
     };
     };
 
 
     try {
     try {
@@ -426,7 +425,6 @@ module.exports = (crowi) => {
         isEnabledStaleNotification: await crowi.configManager.getConfig('crowi', 'customize:isEnabledStaleNotification'),
         isEnabledStaleNotification: await crowi.configManager.getConfig('crowi', 'customize:isEnabledStaleNotification'),
         isAllReplyShown: await crowi.configManager.getConfig('crowi', 'customize:isAllReplyShown'),
         isAllReplyShown: await crowi.configManager.getConfig('crowi', 'customize:isAllReplyShown'),
         isSearchScopeChildrenAsDefault: await crowi.configManager.getConfig('crowi', 'customize:isSearchScopeChildrenAsDefault'),
         isSearchScopeChildrenAsDefault: await crowi.configManager.getConfig('crowi', 'customize:isSearchScopeChildrenAsDefault'),
-        isEnabledMarp: await crowi.configManager.getConfig('crowi', 'customize:isEnabledMarp'),
       };
       };
       const parameters = { action: SupportedAction.ACTION_ADMIN_FUNCTION_UPDATE };
       const parameters = { action: SupportedAction.ACTION_ADMIN_FUNCTION_UPDATE };
       activityEvent.emit('update', res.locals.activity._id, parameters);
       activityEvent.emit('update', res.locals.activity._id, parameters);
@@ -439,6 +437,28 @@ module.exports = (crowi) => {
     }
     }
   });
   });
 
 
+
+  router.put('/presentation', loginRequiredStrictly, adminRequired, addActivity, validator.CustomizePresentation, apiV3FormValidator, async(req, res) => {
+    const requestParams = {
+      'customize:isEnabledMarp': req.body.isEnabledMarp,
+    };
+
+    try {
+      await crowi.configManager.updateConfigsInTheSameNamespace('crowi', requestParams);
+      const customizedParams = {
+        isEnabledMarp: await crowi.configManager.getConfig('crowi', 'customize:isEnabledMarp'),
+      };
+      const parameters = { action: SupportedAction.ACTION_ADMIN_FUNCTION_UPDATE };
+      activityEvent.emit('update', res.locals.activity._id, parameters);
+      return res.apiv3({ customizedParams });
+    }
+    catch (err) {
+      const msg = 'Error occurred in updating presentaion';
+      logger.error('Error', err);
+      return res.apiv3Err(new ErrorV3(msg, 'update-presentation-failed'));
+    }
+  });
+
   /**
   /**
    * @swagger
    * @swagger
    *
    *

+ 26 - 21
apps/app/src/stores/page.tsx

@@ -7,6 +7,7 @@ import type {
   IPageInfo, IPageInfoForOperation,
   IPageInfo, IPageInfoForOperation,
   IRevision, IRevisionHasId,
   IRevision, IRevisionHasId,
 } from '@growi/core';
 } from '@growi/core';
+import { useSWRStatic } from '@growi/core/dist/swr';
 import { isClient, pagePathUtils } from '@growi/core/dist/utils';
 import { isClient, pagePathUtils } from '@growi/core/dist/utils';
 import useSWR, {
 import useSWR, {
   mutate, useSWRConfig, type SWRResponse, type SWRConfiguration,
   mutate, useSWRConfig, type SWRResponse, type SWRConfiguration,
@@ -18,35 +19,36 @@ import useSWRMutation, { type SWRMutationResponse } from 'swr/mutation';
 import { apiGet } from '~/client/util/apiv1-client';
 import { apiGet } from '~/client/util/apiv1-client';
 import { apiv3Get } from '~/client/util/apiv3-client';
 import { apiv3Get } from '~/client/util/apiv3-client';
 import type { IRecordApplicableGrant, IResIsGrantNormalized } from '~/interfaces/page-grant';
 import type { IRecordApplicableGrant, IResIsGrantNormalized } from '~/interfaces/page-grant';
+import type { AxiosResponse } from '~/utils/axios';
 
 
 import type { IPageTagsInfo } from '../interfaces/tag';
 import type { IPageTagsInfo } from '../interfaces/tag';
 
 
 import {
 import {
   useCurrentPathname, useShareLinkId, useIsGuestUser, useIsReadOnlyUser,
   useCurrentPathname, useShareLinkId, useIsGuestUser, useIsReadOnlyUser,
 } from './context';
 } from './context';
-import { useStaticSWR } from './use-static-swr';
+
 
 
 const { isPermalink: _isPermalink } = pagePathUtils;
 const { isPermalink: _isPermalink } = pagePathUtils;
 
 
 
 
 export const useCurrentPageId = (initialData?: Nullable<string>): SWRResponse<Nullable<string>, Error> => {
 export const useCurrentPageId = (initialData?: Nullable<string>): SWRResponse<Nullable<string>, Error> => {
-  return useStaticSWR<Nullable<string>, Error>('currentPageId', initialData);
+  return useSWRStatic<Nullable<string>, Error>('currentPageId', initialData);
 };
 };
 
 
 export const useIsLatestRevision = (initialData?: boolean): SWRResponse<boolean, any> => {
 export const useIsLatestRevision = (initialData?: boolean): SWRResponse<boolean, any> => {
-  return useStaticSWR('isLatestRevision', initialData);
+  return useSWRStatic('isLatestRevision', initialData);
 };
 };
 
 
 export const useIsNotFound = (initialData?: boolean): SWRResponse<boolean, Error> => {
 export const useIsNotFound = (initialData?: boolean): SWRResponse<boolean, Error> => {
-  return useStaticSWR<boolean, Error>('isNotFound', initialData, { fallbackData: false });
+  return useSWRStatic<boolean, Error>('isNotFound', initialData, { fallbackData: false });
 };
 };
 
 
 export const useTemplateTagData = (initialData?: string[]): SWRResponse<string[], Error> => {
 export const useTemplateTagData = (initialData?: string[]): SWRResponse<string[], Error> => {
-  return useStaticSWR<string[], Error>('templateTagData', initialData);
+  return useSWRStatic<string[], Error>('templateTagData', initialData);
 };
 };
 
 
 export const useTemplateBodyData = (initialData?: string): SWRResponse<string, Error> => {
 export const useTemplateBodyData = (initialData?: string): SWRResponse<string, Error> => {
-  return useStaticSWR<string, Error>('templateBodyData', initialData);
+  return useSWRStatic<string, Error>('templateBodyData', initialData);
 };
 };
 
 
 /** "useSWRxCurrentPage" is intended for initial data retrieval only. Use "useSWRMUTxCurrentPage" for revalidation */
 /** "useSWRxCurrentPage" is intended for initial data retrieval only. Use "useSWRMUTxCurrentPage" for revalidation */
@@ -71,6 +73,17 @@ export const useSWRxCurrentPage = (initialData?: IPagePopulatedToShowRevision|nu
   });
   });
 };
 };
 
 
+const getPageApiErrorHandler = (errs: AxiosResponse[]) => {
+  if (!Array.isArray(errs)) { throw Error('error is not array') }
+
+  const statusCode = errs[0].status;
+  if (statusCode === 403 || statusCode === 404) {
+    // for NotFoundPage
+    return null;
+  }
+  throw Error('failed to get page');
+};
+
 export const useSWRMUTxCurrentPage = (): SWRMutationResponse<IPagePopulatedToShowRevision|null> => {
 export const useSWRMUTxCurrentPage = (): SWRMutationResponse<IPagePopulatedToShowRevision|null> => {
   const key = 'currentPage';
   const key = 'currentPage';
 
 
@@ -87,19 +100,9 @@ export const useSWRMUTxCurrentPage = (): SWRMutationResponse<IPagePopulatedToSho
 
 
   return useSWRMutation(
   return useSWRMutation(
     key,
     key,
-    async() => {
-      return apiv3Get<{ page: IPagePopulatedToShowRevision }>('/page', { pageId: currentPageId, shareLinkId, revisionId })
-        .then(result => result.data.page)
-        .catch((errs) => {
-          if (!Array.isArray(errs)) { throw Error('error is not array') }
-          const statusCode = errs[0].status;
-          if (statusCode === 403 || statusCode === 404) {
-            // for NotFoundPage
-            return null;
-          }
-          throw Error('failed to get page');
-        });
-    },
+    () => apiv3Get<{ page: IPagePopulatedToShowRevision }>('/page', { pageId: currentPageId, shareLinkId, revisionId })
+      .then(result => result.data.page)
+      .catch(getPageApiErrorHandler),
     {
     {
       populateCache: true,
       populateCache: true,
       revalidate: false,
       revalidate: false,
@@ -107,10 +110,12 @@ export const useSWRMUTxCurrentPage = (): SWRMutationResponse<IPagePopulatedToSho
   );
   );
 };
 };
 
 
-export const useSWRxPageByPath = (path?: string, config?: SWRConfiguration): SWRResponse<IPagePopulatedToShowRevision, Error> => {
+export const useSWRxPageByPath = (path?: string, config?: SWRConfiguration): SWRResponse<IPagePopulatedToShowRevision|null, Error> => {
   return useSWR(
   return useSWR(
     path != null ? ['/page', path] : null,
     path != null ? ['/page', path] : null,
-    ([endpoint, path]) => apiv3Get<{ page: IPagePopulatedToShowRevision }>(endpoint, { path }).then(result => result.data.page),
+    ([endpoint, path]) => apiv3Get<{ page: IPagePopulatedToShowRevision }>(endpoint, { path })
+      .then(result => result.data.page)
+      .catch(getPageApiErrorHandler),
     {
     {
       ...config,
       ...config,
       keepPreviousData: true,
       keepPreviousData: true,

+ 3 - 6
apps/app/src/styles/_variables.scss

@@ -1,7 +1,3 @@
-//== GROWI Official Color
-$growi-green: #74bc46;
-$growi-blue: #175fa5;
-
 //== Marker Color
 //== Marker Color
 $grw-marker-yellow: #ff6;
 $grw-marker-yellow: #ff6;
 $grw-marker-red: #f6c;
 $grw-marker-red: #f6c;
@@ -20,9 +16,10 @@ $grw-subnav-search-preview-min-height: 90px;
 $grw-navbar-bottom-height: 48px;
 $grw-navbar-bottom-height: 48px;
 $grw-editor-navbar-bottom-height: 48px;
 $grw-editor-navbar-bottom-height: 48px;
 
 
-$grw-sidebar-nav-width: 64px; // !!DO NOT CHANGE!! 'margin-left' for '.css-teprsg' is hardcoded
+$grw-sidebar-nav-width: 48px;
+$grw-sidebar-nav-height: 50px;
 
 
 $grw-logo-width: $grw-sidebar-nav-width;
 $grw-logo-width: $grw-sidebar-nav-width;
-$grw-logomark-width: 36px;
+$grw-logomark-width: 24px;
 
 
 $grw-scroll-margin-top-in-view: 130px;
 $grw-scroll-margin-top-in-view: 130px;

+ 1 - 0
apps/app/src/styles/font-icons.scss

@@ -4,4 +4,5 @@
 @import 'simple-line-icons';
 @import 'simple-line-icons';
 @import 'material-icons/iconfont/filled';
 @import 'material-icons/iconfont/filled';
 @import 'material-icons/iconfont/outlined';
 @import 'material-icons/iconfont/outlined';
+@import 'material-icons/iconfont/round';
 @import '@icon/themify-icons/themify-icons';
 @import '@icon/themify-icons/themify-icons';

+ 26 - 1
apps/app/src/styles/organisms/_wiki.scss

@@ -1,4 +1,4 @@
-@use '@growi/core/scss/bootstrap/init' as bs;
+@use '@growi/core/scss/bootstrap/utilities' as bs;
 
 
 @use '../variables' as var;
 @use '../variables' as var;
 
 
@@ -14,6 +14,13 @@
 
 
   font-size: 16px;
   font-size: 16px;
 
 
+  a {
+    @extend .link-offset-2;
+    @extend .link-underline-opacity-25;
+    @extend .link-underline-opacity-50-hover;
+    text-decoration: underline;
+  }
+
   // @extend .text-break;
   // @extend .text-break;
   // https://github.com/twbs/bootstrap/blob/v4.6.1/scss/utilities/_text.scss#L65-L68
   // https://github.com/twbs/bootstrap/blob/v4.6.1/scss/utilities/_text.scss#L65-L68
   word-break: break-word !important; // Deprecated, but avoids issues with flex containers
   word-break: break-word !important; // Deprecated, but avoids issues with flex containers
@@ -285,3 +292,21 @@
     }
     }
   }
   }
 }
 }
+
+
+// == Colors
+.wiki {
+  a {
+    color: rgba(
+      var(--grw-wiki-link-color-rgb, var(--bs-link-color-rgb)),
+      var(--bs-link-opacity, 1)
+    );
+
+    &:hover {
+      color: rgba(
+        var(--grw-wiki-link-hover-color-rgb, var(--bs-link-hover-color-rgb)),
+        var(--bs-link-opacity, 1)
+      );
+    }
+  }
+}

+ 3 - 0
apps/app/src/utils/axios.ts

@@ -3,6 +3,9 @@ import axios from 'axios';
 import dayjs from 'dayjs';
 import dayjs from 'dayjs';
 import qs from 'qs';
 import qs from 'qs';
 
 
+// eslint-disable-next-line no-restricted-imports
+export * from 'axios';
+
 const customAxios = axios.create({
 const customAxios = axios.create({
   headers: {
   headers: {
     'X-Requested-With': 'XMLHttpRequest',
     'X-Requested-With': 'XMLHttpRequest',

+ 0 - 1
apps/app/vite.styles-prebuilt.config.ts

@@ -7,7 +7,6 @@ export default defineConfig({
     outDir: 'src/styles/prebuilt',
     outDir: 'src/styles/prebuilt',
     rollupOptions: {
     rollupOptions: {
       input: [
       input: [
-        '/src/styles/theme/apply-colors.scss',
         '/src/styles/vendor.scss',
         '/src/styles/vendor.scss',
       ],
       ],
       output: {
       output: {

+ 3 - 0
packages/core/scss/_growi-official-colors.scss

@@ -0,0 +1,3 @@
+//== GROWI Official Color
+$growi-green: #74bc46;
+$growi-blue: #175fa5;

+ 1 - 0
packages/core/scss/bootstrap/_init-stage-1.scss

@@ -0,0 +1 @@
+@import 'bootstrap/scss/functions';

+ 3 - 0
packages/core/scss/bootstrap/_init-stage-2.scss

@@ -0,0 +1,3 @@
+@import 'bootstrap/scss/maps';
+@import 'bootstrap/scss/mixins';
+@import 'bootstrap/scss/utilities';

+ 0 - 13
packages/core/scss/bootstrap/_init.scss

@@ -1,13 +0,0 @@
-@import 'bootstrap/scss/functions';
-
-@import './variables';
-@import 'bootstrap/scss/variables';
-@import 'bootstrap/scss/variables-dark';
-
-@import 'bootstrap/scss/maps';
-// TODO: activate (https://redmine.weseek.co.jp/issues/128307)
-// merge $colors to $theme-colors
-// $theme-colors: map-merge($theme-colors, $colors);
-
-@import 'bootstrap/scss/mixins';
-@import 'bootstrap/scss/utilities';

+ 3 - 28
packages/core/scss/bootstrap/_variables.scss

@@ -1,34 +1,9 @@
 // TODO: activate (https://redmine.weseek.co.jp/issues/128307)
 // TODO: activate (https://redmine.weseek.co.jp/issues/128307)
 
 
-//
 // Variables
 // Variables
-// --------------------------------------------------
-
-//== Colors
 //
 //
-// $primary: variables.$growi-blue !default;
-// $secondary: #6c757d !default;
-// $info: #009fbb !default;
-// $success: #00bb83 !default;
-// $warning: #ffa32b !default;
-// $danger: #ff0a54 !default;
-// $light: #e4e7ea !default;
-// $dark: #343a40 !default;
-// $gray-50: lighten($light, 7%) !default;
-// $gray-100: lighten($light, 4%) !default;
-// $gray-200: $light !default;
-// $gray-300: darken($light, 5%) !default;
-// $gray-400: darken($light, 20%) !default;
-// $gray-500: darken($light, 30%) !default;
-// $gray-550: lighten($dark, 15%) !default;
-// $gray-600: lighten($dark, 10%) !default;
-// $gray-700: lighten($dark, 5%) !default;
-// $gray-800: $dark !default;
-// $gray-900: darken($dark, 5%) !default;
-// $grays: (
-//   '50': $gray-50,
-// ) !default;
-// $red: #ff0a54 !default;
+// Variables should follow the `$component-state-property-size` formula for
+// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.
 
 
 // Options
 // Options
 //
 //
@@ -40,7 +15,7 @@
 //
 //
 // Style anchor elements.
 // Style anchor elements.
 
 
-// $link-hover-decoration: none !default;
+$link-decoration: none;
 
 
 // Grid breakpoints
 // Grid breakpoints
 //
 //

+ 0 - 0
packages/core/scss/bootstrap/_apply.scss → packages/core/scss/bootstrap/apply.scss


+ 8 - 0
packages/core/scss/bootstrap/init.scss

@@ -0,0 +1,8 @@
+@import './init-stage-1';
+
+@import './theming/variables';
+@import './variables';
+@import 'bootstrap/scss/variables';
+@import 'bootstrap/scss/variables-dark';
+
+@import './init-stage-2';

+ 15 - 0
packages/core/scss/bootstrap/theming/_buttons.scss

@@ -0,0 +1,15 @@
+.btn-primary {
+  @include button-variant($primary, $primary);
+}
+
+.btn-outline-primary {
+  @include button-outline-variant($primary);
+}
+
+.btn-secondary {
+  @include button-variant($secondary, $secondary);
+}
+
+.btn-outline-secondary {
+  @include button-outline-variant($secondary);
+}

+ 4 - 0
packages/core/scss/bootstrap/theming/_list-group.scss

@@ -0,0 +1,4 @@
+.list-group {
+  --#{$prefix}list-group-active-bg: #{$list-group-active-bg};
+  --#{$prefix}list-group-active-border-color: #{$list-group-active-border-color};
+}

+ 5 - 0
packages/core/scss/bootstrap/theming/_pagination.scss

@@ -0,0 +1,5 @@
+.pagination {
+  --#{$prefix}pagination-active-color: #{$pagination-active-color};
+  --#{$prefix}pagination-active-bg: #{$pagination-active-bg};
+  --#{$prefix}pagination-active-border-color: #{$pagination-active-border-color};
+}

+ 4 - 0
packages/core/scss/bootstrap/theming/_progress.scss

@@ -0,0 +1,4 @@
+.progress,
+.progress-stacked {
+  --#{$prefix}progress-bar-bg: #{$progress-bar-bg};
+}

+ 41 - 0
packages/core/scss/bootstrap/theming/_root-dark.scss

@@ -0,0 +1,41 @@
+& {
+  --#{$prefix}body-color: #{$body-color-dark};
+  --#{$prefix}body-color-rgb: #{to-rgb($body-color-dark)};
+  --#{$prefix}body-bg: #{$body-bg-dark};
+  --#{$prefix}body-bg-rgb: #{to-rgb($body-bg-dark)};
+
+  --#{$prefix}emphasis-color: #{$body-emphasis-color-dark};
+  --#{$prefix}emphasis-color-rgb: #{to-rgb($body-emphasis-color-dark)};
+
+  --#{$prefix}secondary-color: #{$body-secondary-color-dark};
+  --#{$prefix}secondary-color-rgb: #{to-rgb($body-secondary-color-dark)};
+  --#{$prefix}secondary-bg: #{$body-secondary-bg-dark};
+  --#{$prefix}secondary-bg-rgb: #{to-rgb($body-secondary-bg-dark)};
+
+  --#{$prefix}tertiary-color: #{$body-tertiary-color-dark};
+  --#{$prefix}tertiary-color-rgb: #{to-rgb($body-tertiary-color-dark)};
+  --#{$prefix}tertiary-bg: #{$body-tertiary-bg-dark};
+  --#{$prefix}tertiary-bg-rgb: #{to-rgb($body-tertiary-bg-dark)};
+
+  @each $color, $value in $theme-colors-text-dark {
+    --#{$prefix}#{$color}-text-emphasis: #{$value};
+  }
+
+  @each $color, $value in $theme-colors-bg-subtle-dark {
+    --#{$prefix}#{$color}-bg-subtle: #{$value};
+  }
+
+  @each $color, $value in $theme-colors-border-subtle-dark {
+    --#{$prefix}#{$color}-border-subtle: #{$value};
+  }
+
+  --#{$prefix}link-color: #{$link-color-dark};
+  --#{$prefix}link-hover-color: #{$link-hover-color-dark};
+  --#{$prefix}link-color-rgb: #{to-rgb($link-color-dark)};
+  --#{$prefix}link-hover-color-rgb: #{to-rgb($link-hover-color-dark)};
+
+  --#{$prefix}code-color: #{$code-color-dark};
+
+  --#{$prefix}border-color: #{$border-color-dark};
+  --#{$prefix}border-color-translucent: #{$border-color-translucent-dark};
+}

+ 32 - 0
packages/core/scss/bootstrap/theming/_root-light.scss

@@ -0,0 +1,32 @@
+& {
+  // Root and body
+  --#{$prefix}body-color: #{$body-color};
+  --#{$prefix}body-color-rgb: #{to-rgb($body-color)};
+  --#{$prefix}body-bg: #{$body-bg};
+  --#{$prefix}body-bg-rgb: #{to-rgb($body-bg)};
+
+  --#{$prefix}emphasis-color: #{$body-emphasis-color};
+  --#{$prefix}emphasis-color-rgb: #{to-rgb($body-emphasis-color)};
+
+  --#{$prefix}secondary-color: #{$body-secondary-color};
+  --#{$prefix}secondary-color-rgb: #{to-rgb($body-secondary-color)};
+  --#{$prefix}secondary-bg: #{$body-secondary-bg};
+  --#{$prefix}secondary-bg-rgb: #{to-rgb($body-secondary-bg)};
+
+  --#{$prefix}tertiary-color: #{$body-tertiary-color};
+  --#{$prefix}tertiary-color-rgb: #{to-rgb($body-tertiary-color)};
+  --#{$prefix}tertiary-bg: #{$body-tertiary-bg};
+  --#{$prefix}tertiary-bg-rgb: #{to-rgb($body-tertiary-bg)};
+
+  --#{$prefix}link-color: #{$link-color};
+  --#{$prefix}link-color-rgb: #{to-rgb($link-color)};
+
+  --#{$prefix}link-hover-color: #{$link-hover-color};
+  --#{$prefix}link-hover-color-rgb: #{to-rgb($link-hover-color)};
+
+  --#{$prefix}code-color: #{$code-color};
+  --#{$prefix}highlight-bg: #{$mark-bg};
+
+  --#{$prefix}border-color: #{$border-color};
+  --#{$prefix}border-color-translucent: #{$border-color-translucent};
+}

+ 31 - 0
packages/core/scss/bootstrap/theming/_root.scss

@@ -0,0 +1,31 @@
+& {
+  @each $color, $value in $theme-colors {
+    @if $color == 'primary' or $color == 'secondary' {
+      --#{$prefix}#{$color}: #{$value};
+    }
+  }
+
+  @each $color, $value in $theme-colors-rgb {
+    @if $color == 'primary' or $color == 'secondary' {
+      --#{$prefix}#{$color}-rgb: #{$value};
+    }
+  }
+
+  @each $color, $value in $theme-colors-text {
+    @if $color == 'primary' or $color == 'secondary' {
+      --#{$prefix}#{$color}-text-emphasis: #{$value};
+    }
+  }
+
+  @each $color, $value in $theme-colors-bg-subtle {
+    @if $color == 'primary' or $color == 'secondary' {
+      --#{$prefix}#{$color}-bg-subtle: #{$value};
+    }
+  }
+
+  @each $color, $value in $theme-colors-border-subtle {
+    @if $color == 'primary' or $color == 'secondary' {
+      --#{$prefix}#{$color}-border-subtle: #{$value};
+    }
+  }
+}

+ 5 - 0
packages/core/scss/bootstrap/theming/_tables.scss

@@ -0,0 +1,5 @@
+@each $color, $value in $table-variants {
+  @if $color == 'primary' or $color == 'secondary' {
+    @include table-variant($color, $value);
+  }
+}

+ 16 - 0
packages/core/scss/bootstrap/theming/_variables.scss

@@ -0,0 +1,16 @@
+// Variables
+//
+// Variables should follow the `$component-state-property-size` formula for
+// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.
+
+// Color system
+
+$gray-100: #d2d0ce !default;
+$gray-200: #c9c7c7 !default;
+$gray-300: #bab8b8 !default;
+$gray-400: #adaaaa !default;
+$gray-500: #9a9898 !default;
+$gray-600: #8a8886 !default;
+$gray-700: #585755 !default;
+$gray-800: #323130 !default;
+$gray-900: #171615 !default;

+ 5 - 0
packages/core/scss/bootstrap/theming/apply.scss

@@ -0,0 +1,5 @@
+@import './tables';
+@import './buttons';
+@import './pagination';
+@import './progress';
+@import './list-group';

+ 31 - 0
packages/core/scss/bootstrap/theming/utils/_color-palette.scss

@@ -0,0 +1,31 @@
+@mixin generate-color-palette($color, $value, $shade-color-ratio: 20%, $tint-color-ratio: 20%, $prefix: 'grw-') {
+  $color-900: shade-color($value, $shade-color-ratio * 4);
+  $color-800: shade-color($value, $shade-color-ratio * 3);
+  $color-700: shade-color($value, $shade-color-ratio * 2);
+  $color-600: shade-color($value, $shade-color-ratio);
+  $color-500: $value;
+  $color-400: tint-color($value, $tint-color-ratio);
+  $color-300: tint-color($value, $tint-color-ratio * 2);
+  $color-200: tint-color($value, $tint-color-ratio * 3);
+  $color-100: tint-color($value, $tint-color-ratio * 4);
+
+  --#{$prefix}#{$color}-900: #{$color-900};
+  --#{$prefix}#{$color}-800: #{$color-800};
+  --#{$prefix}#{$color}-700: #{$color-700};
+  --#{$prefix}#{$color}-600: #{$color-600};
+  --#{$prefix}#{$color}-500: #{$color-500};
+  --#{$prefix}#{$color}-400: #{$color-400};
+  --#{$prefix}#{$color}-300: #{$color-300};
+  --#{$prefix}#{$color}-200: #{$color-200};
+  --#{$prefix}#{$color}-100: #{$color-100};
+
+  --#{$prefix}#{$color}-900-rgb: #{to-rgb($color-900)};
+  --#{$prefix}#{$color}-800-rgb: #{to-rgb($color-800)};
+  --#{$prefix}#{$color}-700-rgb: #{to-rgb($color-700)};
+  --#{$prefix}#{$color}-600-rgb: #{to-rgb($color-600)};
+  --#{$prefix}#{$color}-500-rgb: #{to-rgb($color-500)};
+  --#{$prefix}#{$color}-400-rgb: #{to-rgb($color-400)};
+  --#{$prefix}#{$color}-300-rgb: #{to-rgb($color-300)};
+  --#{$prefix}#{$color}-200-rgb: #{to-rgb($color-200)};
+  --#{$prefix}#{$color}-100-rgb: #{to-rgb($color-100)};
+}

+ 4 - 0
packages/core/scss/bootstrap/utilities.scss

@@ -0,0 +1,4 @@
+@import 'init';
+
+@import 'bootstrap/scss/helpers';
+@import 'bootstrap/scss/utilities/api';

+ 1 - 0
packages/editor/src/main.scss

@@ -4,5 +4,6 @@
 $material-icons-font-path: 'material-icons/iconfont/';
 $material-icons-font-path: 'material-icons/iconfont/';
 @import 'material-icons/iconfont/filled';
 @import 'material-icons/iconfont/filled';
 @import 'material-icons/iconfont/outlined';
 @import 'material-icons/iconfont/outlined';
+@import 'material-icons/iconfont/round';
 
 
 @import '@growi/core/scss/flex-expand';
 @import '@growi/core/scss/flex-expand';

+ 3 - 3
packages/presentation/package.json

@@ -31,15 +31,15 @@
     "@marp-team/marp-core": "^3.6.0",
     "@marp-team/marp-core": "^3.6.0",
     "@types/reveal.js": "^4.4.1",
     "@types/reveal.js": "^4.4.1",
     "eslint-plugin-regex": "^1.8.0",
     "eslint-plugin-regex": "^1.8.0",
-    "reveal.js": "^4.4.0",
+    "hast-util-sanitize": "^4.1.0",
+    "hast-util-select": "^5.0.5",
     "mdast-util-frontmatter": "^1.0.0",
     "mdast-util-frontmatter": "^1.0.0",
     "mdast-util-gfm": "^2.0.1",
     "mdast-util-gfm": "^2.0.1",
     "mdast-util-to-markdown": "^1.3.0",
     "mdast-util-to-markdown": "^1.3.0",
-    "hast-util-sanitize": "^4.1.0",
-    "hast-util-select": "^5.0.5",
     "react-markdown": "^8.0.7",
     "react-markdown": "^8.0.7",
     "remark-frontmatter": "^4.0.1",
     "remark-frontmatter": "^4.0.1",
     "remark-stringify": "^10.0.0",
     "remark-stringify": "^10.0.0",
+    "reveal.js": "^4.4.0",
     "unified": "^10.1.2",
     "unified": "^10.1.2",
     "unist-util-find-after": "^4.0.0",
     "unist-util-find-after": "^4.0.0",
     "unist-util-visit": "^4.0.0"
     "unist-util-visit": "^4.0.0"

+ 2 - 2
packages/presentation/src/components/Presentation.module.scss

@@ -12,10 +12,10 @@
     }
     }
     .controls {
     .controls {
       bottom: 24px;
       bottom: 24px;
-      color: var(--color-global);
+      color: var(--bs-body-color);
     }
     }
     .progress {
     .progress {
-      color: var(--accent);
+      color: var(--bs-primary);
     }
     }
   }
   }
 
 

+ 1 - 0
packages/preset-themes/package.json

@@ -13,6 +13,7 @@
     "build": "run-p build:*",
     "build": "run-p build:*",
     "build:libs": "vite -c vite.libs.config.ts build",
     "build:libs": "vite -c vite.libs.config.ts build",
     "build:themes": "vite -c vite.themes.config.ts build",
     "build:themes": "vite -c vite.themes.config.ts build",
+    "clean": "shx rm -rf dist",
     "dev": "run-p dev:*",
     "dev": "run-p dev:*",
     "dev:libs": "yarn build:libs --mode dev",
     "dev:libs": "yarn build:libs --mode dev",
     "dev:themes": "yarn build:themes --mode dev",
     "dev:themes": "yarn build:themes --mode dev",

+ 0 - 26
packages/preset-themes/src/styles/_variables.scss

@@ -1,26 +0,0 @@
-//== GROWI Official Color
-$growi-green: #74bc46;
-$growi-blue: #175fa5;
-
-//== Marker Color
-$grw-marker-yellow: #ff6;
-$grw-marker-red: #f6c;
-$grw-marker-blue: #6cf;
-$grw-marker-cyan: #6ff;
-$grw-marker-green: #6f6;
-
-//== Layout
-$grw-subnav-min-height: 95px;
-$grw-subnav-min-height-md: 115px;
-$grw-subnav-height-on-edit: 95px;
-$grw-subnav-height-lg-on-edit: 50px;
-
-$grw-subnav-search-preview-min-height: 90px;
-
-$grw-navbar-bottom-height: 48px;
-$grw-editor-navbar-bottom-height: 48px;
-
-$grw-sidebar-nav-width: 64px; // !!DO NOT CHANGE!! 'margin-left' for '.css-teprsg' is hardcoded
-
-$grw-logo-width: $grw-sidebar-nav-width;
-$grw-logomark-width: 36px;

+ 256 - 256
packages/preset-themes/src/styles/default.scss

@@ -1,258 +1,258 @@
 @use '@growi/core/scss/bootstrap/init' as bs;
 @use '@growi/core/scss/bootstrap/init' as bs;
 
 
-@use './variables' as var;
-@use './theme/mixins/page-editor-mode-manager';
-@use './theme/hsl-functions' as hsl;
-
-//== Light Mode
-//
-:root[data-bs-theme='light'] {
-  --primary: hsl(var(--primary-hs),var(--primary-l));
-  --primary-hs: 216.7,65%;
-  --primary-l: 20.2%;
-  --secondary: hsl(var(--secondary-hs),var(--secondary-l));
-  --secondary-hs: 208,7%;
-  --secondary-l: 46%;
-  --accent: hsl(var(--accent-hs),var(--accent-l));
-  --accent-hs: 198.6,74.2%;
-  --accent-l: 48.6%;
-
-  // Background colors
-  --bgcolor-global: hsl(var(--bgcolor-global-hs),var(--bgcolor-global-l));
-  --bgcolor-global-hs: 0,0%;
-  --bgcolor-global-l: 100%;
-  --bgcolor-inline-code: #{bs.$gray-100}; //optional
-  --bgcolor-card: #{bs.$gray-100};
-  --bgcolor-blinked-section: #{hsl.alpha(var(--primary),10%)};
-  // --bgcolor-keyword-highlighted: #{$grw-marker-yellow};
-
-  // Font colors
-  --color-global: hsl(var(--color-global-hs),var(--color-global-l));
-  --color-global-hs: 214.1,60%;
-  --color-global-l: 16.7%;
-  --color-reversal: var(--light);
-  // --color-header: #2b2b2b;
-  --color-link: hsl(var(--color-link-hs),var(--color-link-l));
-  --color-link-hs: 228.4,76.3%;
-  --color-link-l: 41.4%;
-  --color-link-hover: #{hsl.lighten(var(--color-link),20%)};
-  --color-link-wiki: var(--color-link);
-  --color-link-wiki-hs: var(--color-link-hs);
-  --color-link-wiki-l: var(--color-link-l);
-  --color-link-wiki-hover: #{hsl.lighten(var(--color-link-wiki),20%)};
-  --color-link-nabvar: #{bs.$gray-500};
-  --color-inline-code: #{darken(bs.$red, 15%)}; // optional
-
-  // List Group colors
-  --color-list: var(--color-global); // optional
-  --bgcolor-list: var(--bgcolor-global); // optional
-  // --color-list-hover: var(--color-global); // optional
-  --bgcolor-list-hover: #{hsl.darken(var(--bgcolor-global),3%)};// optional
-  // --color-list-active: white ; // optional
-  // --bgcolor-list-active: #{hsl.lighten(var(--bgcolor-global),3%)}; // optional
-  // --color-page-list-group-item-meta: #{bs.$gray-500}; // optional
-
-  // Table colors
-  // --color-table: #; // optional
-  // --bgcolor-table: #; // optional
-  // --border-color-table: #; // optional
-  // --color-table-hover: #; // optional
-  // --bgcolor-table-hover: #; // optional
-
-  // Navbar
-  --bgcolor-navbar: #{bs.$gray-900};
-  --bgcolor-navbar-h:0;
-  --bgcolor-navbar-s:0%;
-  --bgcolor-navbar-l:12.94%;
-  --bgcolor-navbar-hs: 0,0%;
-  --bgcolor-search-top-dropdown: var(--accent);
-  --bgcolor-search-top-dropdown-hs: var(--accent-hs);
-  --bgcolor-search-top-dropdown-l: var(--accent-l);
-  --border-image-navbar: linear-gradient(to right, #36c9ff 0%, #36c9ff 33%, #7926ff 66%, #ff2eff 100%);
-
-  // Logo colors
-  --bgcolor-logo: var(--bgcolor-navbar);
-  --fillcolor-logo-mark: hsl(var(--bgcolor-navbar-h),calc(var(--bgcolor-navbar-s) - 20%),calc(var(--bgcolor-navbar-l) + 15%));
-
-  // Sidebar
-  --bgcolor-sidebar: var(--primary);
-  --bgcolor-sidebar-hs: var(--primary-hs);
-  --bgcolor-sidebar-l: var(--primary-l);
-  --bgcolor-sidebar-nav-item-active: rgba(black, 0.37); // optional
-  --text-shadow-sidebar-nav-item-active: 0px 0px 10px #0099ff; // optional
-
-  // Sidebar resize button
-  --color-resize-button: var(--color-reversal);
-  --bgcolor-resize-button: var(--accent);
-  --bgcolor-resize-button-hs: var(--accent-hs);
-  --bgcolor-resize-button-l: var(--accent-l);
-  --color-resize-button-hover: var(--color-reversal);
-  --bgcolor-resize-button-hover: #{hsl.lighten(var(--accent), 5%)};
-
-  // Sidebar contents
-  --color-sidebar-context: var(--color-global);
-  --color-sidebar-context-hs: var(--color-global-hs);
-  --color-sidebar-context-l: var(--color-global-l);
-  --bgcolor-sidebar-context: #{hsl.lighten(var(--primary),77%)};
-  --bgcolor-sidebar-context-hs: var(--primary-hs);
-  --bgcolor-sidebar-context-l: calc(var(--primary-l) + 77%);
-
-  // Sidebar list group
-  // --bgcolor-sidebar-list-group: #{bs.$gray-50}; // optional
-
-  // Subnavigation
-  --bgcolor-subnav: hsl(var(--bgcolor-subnav-hs),var(--bgcolor-subnav-l));
-  --bgcolor-subnav-hs: var(--bgcolor-global-hs);
-  --bgcolor-subnav-l: calc(var(--bgcolor-global-l) - 3%);
-
-  // Tabs
-  // --bordercolor-nav-tabs: #{bs.$gray-300}; // optional
-  // --color-nav-tabs-link-active: #; //optional
-  // --bordercolor-nav-tabs-hover: # # $bordercolor-nav-tabs; // optional
-  // --bordercolor-nav-tabs-active: # # // optional
-
-  // Tags
-  // --color-tags: #; //optional
-  // --bgcolor-tags: #; //optional
-
-  // Icon colors
-  --color-editor-icons: var(--color-global);
-
-  // Border colors
-  --border-color-theme: #{bs.$gray-400};
-  --bordercolor-inline-code: #{bs.$gray-400}; // optional
-
-  // Dropdown colors
-  --bgcolor-dropdown-link-active: #{var.$growi-blue};
-
-  // admin theme box
-  --color-theme-color-box: #{hsl.lighten(var(--primary), 20%)};
-
-  // Button
-  .btn-group.grw-page-editor-mode-manager {
-    .btn.btn-outline-primary {
-      @include page-editor-mode-manager.btn-page-editor-mode-manager (var(--primary),#{hsl.lighten(var(--primary),65%)}, #{hsl.lighten(var(--primary),70%)});
-    }
-  }
-}
-
-//== Dark Mode
-//
-:root[data-bs-theme='dark'] {
-  --primary: hsl(var(--primary-hs),var(--primary-l));
-  --primary-hs: 216.8,85.1%;
-  --primary-l: 44.7%;
-  --secondary: hsl(var(--secondary-hs),var(--secondary-l));
-  --secondary-hs: 208,7%;
-  --secondary-l: 46%;
-  --accent: hsl(var(--accent-hs),var(--accent-l));
-  --accent-hs: 307,100%;
-  --accent-l: 43%;
-
-  // Background colors
-  --bgcolor-global: hsl(var(--bgcolor-global-hs),var(--bgcolor-global-l));
-  --bgcolor-global-hs: 228,12%;
-  --bgcolor-global-l: 8%;
-  --bgcolor-inline-code: #1f1f22; //optional
-  --bgcolor-card: #{hsl.darken(var(--bgcolor-global),5%)};
-  --bgcolor-blinked-section: #{hsl.alpha(var(--primary), 40%)};
-  --bgcolor-keyword-highlighted: #{darken(var.$grw-marker-red, 30%)};
-
-  // Font colors
-  --color-global: hsl(var(--color-global-hs),var(--color-global-l));
-  --color-global-hs: 0,0%;
-  --color-global-l: 74%;
-  --color-reversal: #{bs.$gray-900};
-  // --color-header: desaturate($primary, 20%);
-  --color-link: hsl(var(--color-link-hs),var(--color-link-l));
-  --color-link-hs: 219.3,51.7%;
-  --color-link-l: 65.9%;
-  --color-link-hover: #{hsl.lighten(var(--color-link),10%)};
-  --color-link-wiki: var(--color-link);
-  --color-link-wiki-hs: var(--color-link-hs);
-  --color-link-wiki-l: var(--color-link-l);
-  --color-link-wiki-hover: #{hsl.lighten(var(--color-link-wiki),10%)};
-  --color-link-nabvar: #a7a7a7;
-  --color-inline-code: #c7254e; // optional
-
-  // List Group colors
-  --color-list: var(--color-global); // optional
-  --bgcolor-list: var(--bgcolor-global); // optional
-  // --color-list-hover: var(--color-global); // optional
-  --bgcolor-list-hover: #{hsl.lighten(var(--bgcolor-global),3%)}; // optional
-  // --color-list-active: white ; // optional
-  // --bgcolor-list-active: var(--primary); // optional
-
-  // Table colors
-  // --color-table: #; // optional
-  // --bgcolor-table: #; // optional
-  // --border-color-table: #; // optional
-  // --color-table-hover: #; // optional
-  // --bgcolor-table-hover: #; // optional
-
-  // Navbar
-  --bgcolor-navbar: #2a2929;
-  --bgcolor-search-top-dropdown: var(--accent);
-  --bgcolor-search-top-dropdown-hs: var(--accent-hs);
-  --bgcolor-search-top-dropdown-l: var(--accent-l);
-  --border-image-navbar: linear-gradient(to right, #44bfe3 0%, #b04aff 50%, #ff1794 100%);
-
-  // Logo colors
-  --bgcolor-logo: var(--bgcolor-navbar);
-  --fillcolor-logo-mark: #{bs.$gray-700};
-
-  // Sidebar
-  --bgcolor-sidebar: hsl(var(--bgcolor-sidebar-hs),var(--bgcolor-sidebar-l));
-  --bgcolor-sidebar-hs: 216.7,65%;
-  --bgcolor-sidebar-l: 20.2%;
-  --bgcolor-sidebar-nav-item-active: rgba(#969494, 0.3); // optional
-  --text-shadow-sidebar-nav-item-active: 0px 0px 10px #0099ff; // optional
-  --bgcolor-sidebar-context: hsl(var(--bgcolor-sidebar-context-hs),var(--bgcolor-sidebar-context-l));
-  --bgcolor-sidebar-context-hs: 228,12%;
-  --bgcolor-sidebar-context-l: 16%;
-  // Sidebar resize button
-  --color-resize-button: white;
-  --bgcolor-resize-button: var(--accent);
-  --color-resize-button-hover: white;
-  --bgcolor-resize-button-hover: #{hsl.darken(var(--accent), 5%)};
-  // Sidebar contents
-  --color-sidebar-context: var(--color-global);
-  --color-sidebar-context-hs: var(--color-global-hs);
-  --color-sidebar-context-l: var(--color-global-l);
-  // Sidebar list group
-  // --bgcolor-sidebar-list-group: #1c2a3e; // optional
-
-  // Subnavigation
-  --bgcolor-subnav: hsl(var(--bgcolor-subnav-hs),var(--bgcolor-subnav-l));
-  --bgcolor-subnav-hs: var(--bgcolor-global-hs);
-  --bgcolor-subnav-l: calc(var(--bgcolor-global-l) + 4%);
-
-  // Tabs
-  --bordercolor-nav-tabs: #{bs.$gray-700}; // optional
-  // --color-nav-tabs-link-active: #; //optional
-  --bordercolor-nav-tabs-hover: #666 #666 var(--bordercolor-nav-tabs); // optional
-  --bordercolor-nav-tabs-active: var(--bordercolor-nav-tabs) var(--bordercolor-nav-tabs) var(--bgcolor-global); // optional
-
-  // Tags
-  // --color-tags: #; //optional
-  // --bgcolor-tags: #; //optional
-
-  // Icon colors
-  --color-editor-icons: var(--color-global);
-
-  // Border colors
-  --border-color-theme: hsl(var(--border-color-theme-hs),var(--border-color-theme-l));
-  --border-color-theme-hs: 210,13%;
-  --border-color-theme-l: 71%;
-  --bordercolor-inline-code: var(--secondary); // optional
-
-  // admin theme box
-  --color-theme-color-box: var(--primary);
-
-  //Button
-  .btn-group.grw-page-editor-mode-manager {
-    .btn.btn-outline-primary {
-      @include page-editor-mode-manager.btn-page-editor-mode-manager(#{hsl.lighten(var(--primary), 30%)}, #{hsl.lighten(var(--primary), 20%)}, var(--primary), #{hsl.darken(var(--primary), 20%)});
-    }
-  }
-}
+// @use './variables' as var;
+// @use './theme/mixins/page-editor-mode-manager';
+// @use './theme/hsl-functions' as hsl;
+
+// //== Light Mode
+// //
+// :root[data-bs-theme='light'] {
+//   --primary: hsl(var(--primary-hs),var(--primary-l));
+//   --primary-hs: 216.7,65%;
+//   --primary-l: 20.2%;
+//   --secondary: hsl(var(--secondary-hs),var(--secondary-l));
+//   --secondary-hs: 208,7%;
+//   --secondary-l: 46%;
+//   --accent: hsl(var(--accent-hs),var(--accent-l));
+//   --accent-hs: 198.6,74.2%;
+//   --accent-l: 48.6%;
+
+//   // Background colors
+//   --bgcolor-global: hsl(var(--bgcolor-global-hs),var(--bgcolor-global-l));
+//   --bgcolor-global-hs: 0,0%;
+//   --bgcolor-global-l: 100%;
+//   --bgcolor-inline-code: #{bs.$gray-100}; //optional
+//   --bgcolor-card: #{bs.$gray-100};
+//   --bgcolor-blinked-section: #{hsl.alpha(var(--primary),10%)};
+//   // --bgcolor-keyword-highlighted: #{$grw-marker-yellow};
+
+//   // Font colors
+//   --color-global: hsl(var(--color-global-hs),var(--color-global-l));
+//   --color-global-hs: 214.1,60%;
+//   --color-global-l: 16.7%;
+//   --color-reversal: var(--light);
+//   // --color-header: #2b2b2b;
+//   --color-link: hsl(var(--color-link-hs),var(--color-link-l));
+//   --color-link-hs: 228.4,76.3%;
+//   --color-link-l: 41.4%;
+//   --color-link-hover: #{hsl.lighten(var(--color-link),20%)};
+//   --color-link-wiki: var(--color-link);
+//   --color-link-wiki-hs: var(--color-link-hs);
+//   --color-link-wiki-l: var(--color-link-l);
+//   --color-link-wiki-hover: #{hsl.lighten(var(--color-link-wiki),20%)};
+//   --color-link-nabvar: #{bs.$gray-500};
+//   --color-inline-code: #{darken(bs.$red, 15%)}; // optional
+
+//   // List Group colors
+//   --color-list: var(--color-global); // optional
+//   --bgcolor-list: var(--bgcolor-global); // optional
+//   // --color-list-hover: var(--color-global); // optional
+//   --bgcolor-list-hover: #{hsl.darken(var(--bgcolor-global),3%)};// optional
+//   // --color-list-active: white ; // optional
+//   // --bgcolor-list-active: #{hsl.lighten(var(--bgcolor-global),3%)}; // optional
+//   // --color-page-list-group-item-meta: #{bs.$gray-500}; // optional
+
+//   // Table colors
+//   // --color-table: #; // optional
+//   // --bgcolor-table: #; // optional
+//   // --border-color-table: #; // optional
+//   // --color-table-hover: #; // optional
+//   // --bgcolor-table-hover: #; // optional
+
+//   // Navbar
+//   --bgcolor-navbar: #{bs.$gray-900};
+//   --bgcolor-navbar-h:0;
+//   --bgcolor-navbar-s:0%;
+//   --bgcolor-navbar-l:12.94%;
+//   --bgcolor-navbar-hs: 0,0%;
+//   --bgcolor-search-top-dropdown: var(--accent);
+//   --bgcolor-search-top-dropdown-hs: var(--accent-hs);
+//   --bgcolor-search-top-dropdown-l: var(--accent-l);
+//   --border-image-navbar: linear-gradient(to right, #36c9ff 0%, #36c9ff 33%, #7926ff 66%, #ff2eff 100%);
+
+//   // Logo colors
+//   --bgcolor-logo: var(--bgcolor-navbar);
+//   --fillcolor-logo-mark: hsl(var(--bgcolor-navbar-h),calc(var(--bgcolor-navbar-s) - 20%),calc(var(--bgcolor-navbar-l) + 15%));
+
+//   // Sidebar
+//   --bgcolor-sidebar: var(--primary);
+//   --bgcolor-sidebar-hs: var(--primary-hs);
+//   --bgcolor-sidebar-l: var(--primary-l);
+//   --bgcolor-sidebar-nav-item-active: rgba(black, 0.37); // optional
+//   --text-shadow-sidebar-nav-item-active: 0px 0px 10px #0099ff; // optional
+
+//   // Sidebar resize button
+//   --color-resize-button: var(--color-reversal);
+//   --bgcolor-resize-button: var(--accent);
+//   --bgcolor-resize-button-hs: var(--accent-hs);
+//   --bgcolor-resize-button-l: var(--accent-l);
+//   --color-resize-button-hover: var(--color-reversal);
+//   --bgcolor-resize-button-hover: #{hsl.lighten(var(--accent), 5%)};
+
+//   // Sidebar contents
+//   --color-sidebar-context: var(--color-global);
+//   --color-sidebar-context-hs: var(--color-global-hs);
+//   --color-sidebar-context-l: var(--color-global-l);
+//   --bgcolor-sidebar-context: #{hsl.lighten(var(--primary),77%)};
+//   --bgcolor-sidebar-context-hs: var(--primary-hs);
+//   --bgcolor-sidebar-context-l: calc(var(--primary-l) + 77%);
+
+//   // Sidebar list group
+//   // --bgcolor-sidebar-list-group: #{bs.$gray-50}; // optional
+
+//   // Subnavigation
+//   --bgcolor-subnav: hsl(var(--bgcolor-subnav-hs),var(--bgcolor-subnav-l));
+//   --bgcolor-subnav-hs: var(--bgcolor-global-hs);
+//   --bgcolor-subnav-l: calc(var(--bgcolor-global-l) - 3%);
+
+//   // Tabs
+//   // --bordercolor-nav-tabs: #{bs.$gray-300}; // optional
+//   // --color-nav-tabs-link-active: #; //optional
+//   // --bordercolor-nav-tabs-hover: # # $bordercolor-nav-tabs; // optional
+//   // --bordercolor-nav-tabs-active: # # // optional
+
+//   // Tags
+//   // --color-tags: #; //optional
+//   // --bgcolor-tags: #; //optional
+
+//   // Icon colors
+//   --color-editor-icons: var(--color-global);
+
+//   // Border colors
+//   --border-color-theme: #{bs.$gray-400};
+//   --bordercolor-inline-code: #{bs.$gray-400}; // optional
+
+//   // Dropdown colors
+//   --bgcolor-dropdown-link-active: #{var.$growi-blue};
+
+//   // admin theme box
+//   --color-theme-color-box: #{hsl.lighten(var(--primary), 20%)};
+
+//   // Button
+//   .btn-group.grw-page-editor-mode-manager {
+//     .btn.btn-outline-primary {
+//       @include page-editor-mode-manager.btn-page-editor-mode-manager (var(--primary),#{hsl.lighten(var(--primary),65%)}, #{hsl.lighten(var(--primary),70%)});
+//     }
+//   }
+// }
+
+// //== Dark Mode
+// //
+// :root[data-bs-theme='dark'] {
+//   --primary: hsl(var(--primary-hs),var(--primary-l));
+//   --primary-hs: 216.8,85.1%;
+//   --primary-l: 44.7%;
+//   --secondary: hsl(var(--secondary-hs),var(--secondary-l));
+//   --secondary-hs: 208,7%;
+//   --secondary-l: 46%;
+//   --accent: hsl(var(--accent-hs),var(--accent-l));
+//   --accent-hs: 307,100%;
+//   --accent-l: 43%;
+
+//   // Background colors
+//   --bgcolor-global: hsl(var(--bgcolor-global-hs),var(--bgcolor-global-l));
+//   --bgcolor-global-hs: 228,12%;
+//   --bgcolor-global-l: 8%;
+//   --bgcolor-inline-code: #1f1f22; //optional
+//   --bgcolor-card: #{hsl.darken(var(--bgcolor-global),5%)};
+//   --bgcolor-blinked-section: #{hsl.alpha(var(--primary), 40%)};
+//   --bgcolor-keyword-highlighted: #{darken(var.$grw-marker-red, 30%)};
+
+//   // Font colors
+//   --color-global: hsl(var(--color-global-hs),var(--color-global-l));
+//   --color-global-hs: 0,0%;
+//   --color-global-l: 74%;
+//   --color-reversal: #{bs.$gray-900};
+//   // --color-header: desaturate($primary, 20%);
+//   --color-link: hsl(var(--color-link-hs),var(--color-link-l));
+//   --color-link-hs: 219.3,51.7%;
+//   --color-link-l: 65.9%;
+//   --color-link-hover: #{hsl.lighten(var(--color-link),10%)};
+//   --color-link-wiki: var(--color-link);
+//   --color-link-wiki-hs: var(--color-link-hs);
+//   --color-link-wiki-l: var(--color-link-l);
+//   --color-link-wiki-hover: #{hsl.lighten(var(--color-link-wiki),10%)};
+//   --color-link-nabvar: #a7a7a7;
+//   --color-inline-code: #c7254e; // optional
+
+//   // List Group colors
+//   --color-list: var(--color-global); // optional
+//   --bgcolor-list: var(--bgcolor-global); // optional
+//   // --color-list-hover: var(--color-global); // optional
+//   --bgcolor-list-hover: #{hsl.lighten(var(--bgcolor-global),3%)}; // optional
+//   // --color-list-active: white ; // optional
+//   // --bgcolor-list-active: var(--primary); // optional
+
+//   // Table colors
+//   // --color-table: #; // optional
+//   // --bgcolor-table: #; // optional
+//   // --border-color-table: #; // optional
+//   // --color-table-hover: #; // optional
+//   // --bgcolor-table-hover: #; // optional
+
+//   // Navbar
+//   --bgcolor-navbar: #2a2929;
+//   --bgcolor-search-top-dropdown: var(--accent);
+//   --bgcolor-search-top-dropdown-hs: var(--accent-hs);
+//   --bgcolor-search-top-dropdown-l: var(--accent-l);
+//   --border-image-navbar: linear-gradient(to right, #44bfe3 0%, #b04aff 50%, #ff1794 100%);
+
+//   // Logo colors
+//   --bgcolor-logo: var(--bgcolor-navbar);
+//   --fillcolor-logo-mark: #{bs.$gray-700};
+
+//   // Sidebar
+//   --bgcolor-sidebar: hsl(var(--bgcolor-sidebar-hs),var(--bgcolor-sidebar-l));
+//   --bgcolor-sidebar-hs: 216.7,65%;
+//   --bgcolor-sidebar-l: 20.2%;
+//   --bgcolor-sidebar-nav-item-active: rgba(#969494, 0.3); // optional
+//   --text-shadow-sidebar-nav-item-active: 0px 0px 10px #0099ff; // optional
+//   --bgcolor-sidebar-context: hsl(var(--bgcolor-sidebar-context-hs),var(--bgcolor-sidebar-context-l));
+//   --bgcolor-sidebar-context-hs: 228,12%;
+//   --bgcolor-sidebar-context-l: 16%;
+//   // Sidebar resize button
+//   --color-resize-button: white;
+//   --bgcolor-resize-button: var(--accent);
+//   --color-resize-button-hover: white;
+//   --bgcolor-resize-button-hover: #{hsl.darken(var(--accent), 5%)};
+//   // Sidebar contents
+//   --color-sidebar-context: var(--color-global);
+//   --color-sidebar-context-hs: var(--color-global-hs);
+//   --color-sidebar-context-l: var(--color-global-l);
+//   // Sidebar list group
+//   // --bgcolor-sidebar-list-group: #1c2a3e; // optional
+
+//   // Subnavigation
+//   --bgcolor-subnav: hsl(var(--bgcolor-subnav-hs),var(--bgcolor-subnav-l));
+//   --bgcolor-subnav-hs: var(--bgcolor-global-hs);
+//   --bgcolor-subnav-l: calc(var(--bgcolor-global-l) + 4%);
+
+//   // Tabs
+//   --bordercolor-nav-tabs: #{bs.$gray-700}; // optional
+//   // --color-nav-tabs-link-active: #; //optional
+//   --bordercolor-nav-tabs-hover: #666 #666 var(--bordercolor-nav-tabs); // optional
+//   --bordercolor-nav-tabs-active: var(--bordercolor-nav-tabs) var(--bordercolor-nav-tabs) var(--bgcolor-global); // optional
+
+//   // Tags
+//   // --color-tags: #; //optional
+//   // --bgcolor-tags: #; //optional
+
+//   // Icon colors
+//   --color-editor-icons: var(--color-global);
+
+//   // Border colors
+//   --border-color-theme: hsl(var(--border-color-theme-hs),var(--border-color-theme-l));
+//   --border-color-theme-hs: 210,13%;
+//   --border-color-theme-l: 71%;
+//   --bordercolor-inline-code: var(--secondary); // optional
+
+//   // admin theme box
+//   --color-theme-color-box: var(--primary);
+
+//   //Button
+//   .btn-group.grw-page-editor-mode-manager {
+//     .btn.btn-outline-primary {
+//       @include page-editor-mode-manager.btn-page-editor-mode-manager(#{hsl.lighten(var(--primary), 30%)}, #{hsl.lighten(var(--primary), 20%)}, var(--primary), #{hsl.darken(var(--primary), 20%)});
+//     }
+//   }
+// }

+ 334 - 258
packages/preset-themes/src/styles/mono-blue.scss

@@ -1,264 +1,340 @@
-@use '@growi/core/scss/bootstrap/init' as bs;
+:root[data-bs-theme='light'] {
+  @import '@growi/core/scss/bootstrap/init-stage-1';
+  @import '@growi/core/scss/bootstrap/theming/variables';
+  @import '@growi/core/scss/bootstrap/theming/utils/color-palette';
 
 
-@use './variables' as var;
-@use './theme/mixins/page-editor-mode-manager';
-@use './theme/hsl-functions' as hsl;
+  $primary: #409cb9;
+  $secondary: $gray-600;
+  $highlight: #93e3ea;
 
 
-:root[data-bs-theme='light'] {
-  // Theme colors
-  --primary: hsl(var(--primary-hs),var(--primary-l)) !important;
-  --primary-hs: 197,100%;
-  --primary-l: 24%;
-  --secondary: hsl(var(--secondary-hs),var(--secondary-l)) !important;
-  --secondary-hs: 208,7%;
-  --secondary-l: 46%;
-  --accentcolor: hsl(var(--accentcolor-hs),var(--accentcolor-l));
-  --accentcolor-hs: 210,14%;
-  --accentcolor-l: 89%;
-
-  // Background colors
-  --bgcolor-global: hsl(var(--bgcolor-global-hs),var(--bgcolor-global-l));
-  --bgcolor-global-hs: 200,60%;
-  --bgcolor-global-l: 98%;
-  --bgcolor-inline-code: #{bs.$gray-100}; //optional
-  --bgcolor-card: #{hsl.darken(var(--bgcolor-global), 5%)};
-  --bgcolor-blinked-section: #{hsl.alpha(var(--primary),10%)};
-  //--bgcolor-keyword-highlighted: #{$grw-marker-yellow};
-
-  // Font colors
-  --color-global: var(--primary);
-  --color-global-hs: var(--primary-hs);
-  --color-global-l: var(--primary-l);
-  --color-reversal: #{bs.$gray-100};
-  --color-link: #{hsl.lighten(var(--primary),5%)};
-  --color-link-hs: var(--primary-hs);
-  --color-link-l: calc(var(--primary-l) + 5%);
-  --color-link-hover: #{hsl.lighten(var(--color-link), 12%)};
-  --color-link-wiki: #{hsl.lighten(var(--primary),20%)};
-  --color-link-wiki-hs: var(--primary-hs);
-  --color-link-wiki-l: calc(var(--primary-l) + 20%);
-  --color-link-wiki-hover: #{hsl.lighten(var(--primary),40%)};
-  --color-link-nabvar: var(--color-reversal);
-  --color-inline-code: #c7254e; // optional
-  --color-search: #c0d6df;
-
-  // List Group colors
-  // --color-list: var(--color-global);
-  --bgcolor-list: transparent;
-  --color-list-hover: var(--color-search);
-  --bgcolor-list-hover: #{hsl.lighten(var(--primary), 70%)};
-  // --color-list-active: var(--color-reversal);
-  // --bgcolor-list-active: var(--primary);
-
-  // Navbar
-  --bgcolor-navbar: hsl(var(--bgcolor-navbar-hs),var(--bgcolor-navbar-l));
-  --bgcolor-navbar-h: 0;
-  --bgcolor-navbar-s: 1%;
-  --bgcolor-navbar-l: 16%;
-  --bgcolor-navbar-hs: 0,1%;
-  --bgcolor-search-top-dropdown: var(--primary);
-  --bgcolor-search-top-dropdown-hs: var(--primary-hs);
-  --bgcolor-search-top-dropdown-l: var(--primary-l);
-  --border-image-navbar: linear-gradient(to right, #54bafd 0%, #3d98a3 50%, #708b0b 100%);
-
-  // Logo colors
-  --bgcolor-logo: var(--primary);
-  --fillcolor-logo-mark: hsl(var(--bgcolor-navbar-h),calc(var(--bgcolor-navbar-s) - 10%),calc(var(--bgcolor-navbar-l) + 15%));
-
-  // Sidebar
-  --bgcolor-sidebar: var(--primary);
-  --bgcolor-sidebar-hs: var(--primary-hs);
-  --bgcolor-sidebar-l: var(--primary-l);
-
-  // --bgcolor-sidebar-nav-item-active: rgba(#, 0.37); // optional
-  --text-shadow-sidebar-nav-item-active: 0px 0px 10px #0099ff; // optional
-
-  // Sidebar resize button
-  --color-resize-button: var(--color-reversal);
-  --bgcolor-resize-button: hsl(var(--bgcolor-resize-button-hs),var(--bgcolor-resize-button-l));
-  --bgcolor-resize-button-hs: 199,74%;
-  --bgcolor-resize-button-l: 49%;
-  --color-resize-button-hover: var(--color-reversal);
-  --bgcolor-resize-button-hover: #{hsl.lighten(var(--bgcolor-resize-button), 5%)};
-
-  // Sidebar contents
-  --color-sidebar-context: var(--color-global);
-  --color-sidebar-context-hs: var(--color-global-hs);
-  --color-sidebar-context-l: var(--color-global-l);
-  --bgcolor-sidebar-context: hsl(var(--bgcolor-sidebar-context-hs),var(--bgcolor-sidebar-context-l));
-  --bgcolor-sidebar-context-hs: 193,100%;
-  --bgcolor-sidebar-context-l: 97%;
-
-  // Sidebar list group
-  // --bgcolor-sidebar-list-group: #; // optional
-
-  // Subnavigation
-  --bgcolor-subnav: hsl(var(--bgcolor-subnav-hs),var(--bgcolor-subnav-l));
-  --bgcolor-subnav-hs: var(--bgcolor-global-hs);
-  --bgcolor-subnav-l: calc(var(--bgcolor-global-l) - 3%);
-
-  // Icon colors
-  --color-editor-icons: var(--color-global);
-
-  // Border colors
-  --border-color-theme: var(--accentcolor);
-  --bordercolor-inline-code: #ccc8c8; // optional
-
-  // admin theme box
-  --color-theme-color-box: #{hsl.lighten(var(--primary), 20%)};
-
-  // Navs {
-  .nav-tabs {
-    border-bottom: var(--accentcolor) 1px solid;
-    .nav-link {
-      &:hover {
-        border-color: #{hsl.lighten(var(--accentcolor),10%)};
-        border-bottom: none;
-      }
-      &.active {
-        background-color: transparent;
-      }
-    }
-  }
-  // Button
-  .btn-group.grw-page-editor-mode-manager {
-    .btn.btn-outline-primary {
-      @include page-editor-mode-manager.btn-page-editor-mode-manager(var(--primary), #{hsl.lighten(var(--primary), 65%)}, #{hsl.lighten(var(--primary), 70%)});
-    }
-  }
+  @include generate-color-palette('primary', $primary);
+  @include generate-color-palette('highlight', $highlight);
+
+  $body-color:                $gray-900;
+  $body-bg:                   white;
+
+  $body-secondary-color:      rgba($body-color, .75);
+  $body-secondary-bg:         $gray-200;
+
+  $body-tertiary-color:       rgba($body-color, .5);
+  $body-tertiary-bg:          $gray-100;
+
+  $border-color:              $gray-300;
+
+  $link-color:                $gray-800;
+
+  @import 'bootstrap/scss/variables';
+  @import 'bootstrap/scss/variables-dark';
+
+  @import '@growi/core/scss/bootstrap/init-stage-2';
+
+  @import '@growi/core/scss/bootstrap/theming/root';
+  @import '@growi/core/scss/bootstrap/theming/root-light';
+  @import '@growi/core/scss/bootstrap/theming/apply';
+
+  --grw-wiki-link-color-rgb: var(--grw-primary-500-rgb);
+  --grw-wiki-link-hover-color-rgb: var(--grw-primary-700-rgb);
 }
 }
 
 
 :root[data-bs-theme='dark'] {
 :root[data-bs-theme='dark'] {
-  // Theme colors
-  --primary: hsl(var(--primary-hs),var(--primary-l)) !important;
-  --primary-hs: 197,100%;
-  --primary-l: 39%;
-  --secondary: hsl(var(--secondary-hs),var(--secondary-l)) !important;
-  --secondary-hs: 208,7%;
-  --secondary-l: 46%;
-  --accentcolor: hsl(var(--accentcolor-hs),var(--accentcolor-l));
-  --accentcolor-hs: 203,78%;
-  --accentcolor-l: 35%;
-
-  // Background colors
-  --bgcolor-global: hsl(var(--bgcolor-global-hs),var(--bgcolor-global-l));
-  --bgcolor-global-hs: 203,77%;
-  --bgcolor-global-l: 10%;
-  --bgcolor-navbar: hsl(var(--bgcolor-navbar-hs),var(--bgcolor-navbar-l));
-  --bgcolor-navbar-hs: 201,20%;
-  --bgcolor-navbar-l: 19%;
-  --bgcolor-inline-code: #1f1f22; //optional
-  --bgcolor-card: #{hsl.darken(var(--bgcolor-global), 5%)};
-  --bgcolor-blinked-section: #{hsl.alpha(var(--primary),50%)};
-  --bgcolor-keyword-highlighted: #{darken(var.$grw-marker-red, 30%)};
-
-  // Font colors
-  --color-global: hsl(var(--color-global-hs),var(--color-global-l));
-  --color-global-hs: 180,1%;
-  --color-global-l: 83%;
-  --color-reversal: #{bs.$gray-100};
-  --color-link: hsl(var(--color-link-hs),var(--color-link-l));
-  --color-link-hs: 201,75%;
-  --color-link-l: 77%;
-  --color-link-hover: #{hsl.darken(var(--color-link), 12%)};
-  --color-link-wiki: #{hsl.lighten(var(--primary),20%)};
-  --color-link-wiki-hs: var(--primary-hs);
-  --color-link-wiki-l: calc(var(--primary-l) + 20%);
-  --color-link-wiki-hover: #{hsl.lighten(var(--primary),40%)};
-  --color-link-nabvar: var(--color-reversal);
-  --color-inline-code: #c7254e; // optional
-  --color-search: #000102;
-
-  // List Group colors
-  // --color-list: var(--color-global);
-  --bgcolor-list: transparent;
-  --color-list-hover: #16617d;
-  // --bgcolor-list-hover: #{hsl.lighten(var(--bgcolor-global),3%)}; // optional
-  // --color-list-active: var(--color-reversal);
-  // --bgcolor-list-active: var(--primary);
-
-  // Navbar
-  --bgcolor-navbar: hsl(var(--bgcolor-navbar-hs),var(--bgcolor-navbar-l));
-  --bgcolor-navbar-h: 0;
-  --bgcolor-navbar-s: 1%;
-  --bgcolor-navbar-l: 16%;
-  --bgcolor-navbar-hs:var(--bgcolor-navbar-h),var(--bgcolor-navbar-s);
-  --bgcolor-search-top-dropdown: var(--primary);
-  --bgcolor-search-top-dropdown-hs: var(--primary-hs);
-  --bgcolor-search-top-dropdown-l: var(--primary-l);
-  --border-image-navbar: linear-gradient(to right, #54bafd 0%, #3d98a3 50%, #708b0b 100%);
-
-  // Logo colors
-  --bgcolor-logo: #13191c;
-  --fillcolor-logo-mark: hsl(var(--bgcolor-navbar-h),calc(var(--bgcolor-navbar-s) - 10%),calc(var(--bgcolor-navbar-l) + 15%));
-  // --fillcolor-logo-mark: #4e5a60;
-
-  // Sidebar
-  --bgcolor-sidebar: hsl(var(--bgcolor-sidebar-hs),var(--bgcolor-sidebar-l));
-  --bgcolor-sidebar-hs: 196,70%;
-  --bgcolor-sidebar-l: 29%;
-  // --bgcolor-sidebar-nav-item-active: rgba(#, 0.3); // optional
-  --text-shadow-sidebar-nav-item-active: 0px 0px 10px #0099ff; // optional
-
-  // Sidebar resize button
-  --color-resize-button: var(--color-global);
-  --bgcolor-resize-button: var(--primary);
-  --bgcolor-resize-button-hs: var(--primary-hs);
-  --bgcolor-resize-button-l: var(--primary-l);
-  --color-resize-button-hover: var(--color-global);
-  --bgcolor-resize-button-hover: #{hsl.darken(var(--primary), 5%)};
-
-  // Sidebar contents
-  --bgcolor-sidebar-context: #{hsl.darken(var(--bgcolor-sidebar), 13%)};
-  --bgcolor-sidebar-context-hs: var(--bgcolor-sidebar-hs);
-  --bgcolor-sidebar-context-l: calc(var(--bgcolor-sidebar-l) - 13%);
-  --color-sidebar-context: var(--color-global);
-  --color-sidebar-context-hs: var(--color-global-hs);
-  --color-sidebar-context-l: var(--color-global-l);
-
-  // Sidebar list group
-  // --bgcolor-sidebar-list-group: #; // optional
-
-  // Subnavigation
-  --bgcolor-subnav: hsl(var(--bgcolor-subnav-hs),var(--bgcolor-subnav-l));
-  --bgcolor-subnav-hs: var(--bgcolor-global-hs);
-  --bgcolor-subnav-l: calc(var(--bgcolor-global-l) - 3%);
-
-  // Icon colors
-  --color-editor-icons: var(--color-global);
-
-  // Border colors
-  --border-color-theme: var(--accentcolor);
-  --bordercolor-inline-code: #4d4d4d; // optional
-
-  // admin theme box
-  --color-theme-color-box: var(--primary);
-
-  // Navs
-  .nav-tabs {
-    border-bottom: var(--accentcolor) 1px solid;
-    .nav-link {
-      &:hover {
-        border-color: #{hsl.lighten(var(--accentcolor), 10%)};
-        border-bottom: none;
-      }
-      &.active {
-        color: var(--color-link);
-        background-color: transparent;
-        border-color: var(--accentcolor);
-      }
-    }
-  }
-
-  // Table
-  .table {
-    color: white;
-  }
-
-  // Button
-  .btn-group.grw-page-editor-mode-manager {
-    .btn.btn-outline-primary {
-      @include page-editor-mode-manager.btn-page-editor-mode-manager(#{hsl.lighten(var(--primary), 30%)}, var(--primary), #{hsl.darken(var(--primary), 10%)}, #{hsl.darken(var(--primary), 20%)});
-    }
-  }
+  @import '@growi/core/scss/bootstrap/init-stage-1';
+  @import '@growi/core/scss/bootstrap/theming/variables';
+  @import '@growi/core/scss/bootstrap/theming/utils/color-palette';
+
+  $primary: #439cb9;
+  $secondary: $gray-500;
+  $highlight: #64a9ed;
+
+  @include generate-color-palette('primary', $primary);
+  @include generate-color-palette('highlight', $highlight);
+
+  $body-color-dark:                   $gray-200;
+  $body-bg-dark:                      #16202c;
+
+  $body-secondary-color-dark:         rgba($body-color-dark, .75);
+  $body-secondary-bg-dark:            $gray-800;
+
+  $body-tertiary-color-dark:          rgba($body-color-dark, .5);
+  $body-tertiary-bg-dark:             mix($gray-800, $gray-900, 50%);
+
+  $border-color-dark:                 $gray-700;
+
+  $link-color-dark:                   $gray-300;
+
+  @import 'bootstrap/scss/variables';
+  @import 'bootstrap/scss/variables-dark';
+
+  @import '@growi/core/scss/bootstrap/init-stage-2';
+
+  @import '@growi/core/scss/bootstrap/theming/root';
+  @import '@growi/core/scss/bootstrap/theming/root-dark';
+  @import '@growi/core/scss/bootstrap/theming/apply';
+
+  --grw-wiki-link-color-rgb: var(--grw-primary-500-rgb);
+  --grw-wiki-link-hover-color-rgb: var(--grw-primary-300-rgb);
 }
 }
+
+// @use '@growi/core/scss/bootstrap/init' as bs;
+
+// @use './variables' as var;
+// @use './theme/mixins/page-editor-mode-manager';
+// @use './theme/hsl-functions' as hsl;
+
+// :root[data-bs-theme='light'] {
+//   // Theme colors
+//   --primary: hsl(var(--primary-hs),var(--primary-l)) !important;
+//   --primary-hs: 197,100%;
+//   --primary-l: 24%;
+//   --secondary: hsl(var(--secondary-hs),var(--secondary-l)) !important;
+//   --secondary-hs: 208,7%;
+//   --secondary-l: 46%;
+//   --accentcolor: hsl(var(--accentcolor-hs),var(--accentcolor-l));
+//   --accentcolor-hs: 210,14%;
+//   --accentcolor-l: 89%;
+
+//   // Background colors
+//   --bgcolor-global: hsl(var(--bgcolor-global-hs),var(--bgcolor-global-l));
+//   --bgcolor-global-hs: 200,60%;
+//   --bgcolor-global-l: 98%;
+//   --bgcolor-inline-code: #{bs.$gray-100}; //optional
+//   --bgcolor-card: #{hsl.darken(var(--bgcolor-global), 5%)};
+//   --bgcolor-blinked-section: #{hsl.alpha(var(--primary),10%)};
+//   //--bgcolor-keyword-highlighted: #{$grw-marker-yellow};
+
+//   // Font colors
+//   --color-global: var(--primary);
+//   --color-global-hs: var(--primary-hs);
+//   --color-global-l: var(--primary-l);
+//   --color-reversal: #{bs.$gray-100};
+//   --color-link: #{hsl.lighten(var(--primary),5%)};
+//   --color-link-hs: var(--primary-hs);
+//   --color-link-l: calc(var(--primary-l) + 5%);
+//   --color-link-hover: #{hsl.lighten(var(--color-link), 12%)};
+//   --color-link-wiki: #{hsl.lighten(var(--primary),20%)};
+//   --color-link-wiki-hs: var(--primary-hs);
+//   --color-link-wiki-l: calc(var(--primary-l) + 20%);
+//   --color-link-wiki-hover: #{hsl.lighten(var(--primary),40%)};
+//   --color-link-nabvar: var(--color-reversal);
+//   --color-inline-code: #c7254e; // optional
+//   --color-search: #c0d6df;
+
+//   // List Group colors
+//   // --color-list: var(--color-global);
+//   --bgcolor-list: transparent;
+//   --color-list-hover: var(--color-search);
+//   --bgcolor-list-hover: #{hsl.lighten(var(--primary), 70%)};
+//   // --color-list-active: var(--color-reversal);
+//   // --bgcolor-list-active: var(--primary);
+
+//   // Navbar
+//   --bgcolor-navbar: hsl(var(--bgcolor-navbar-hs),var(--bgcolor-navbar-l));
+//   --bgcolor-navbar-h: 0;
+//   --bgcolor-navbar-s: 1%;
+//   --bgcolor-navbar-l: 16%;
+//   --bgcolor-navbar-hs: 0,1%;
+//   --bgcolor-search-top-dropdown: var(--primary);
+//   --bgcolor-search-top-dropdown-hs: var(--primary-hs);
+//   --bgcolor-search-top-dropdown-l: var(--primary-l);
+//   --border-image-navbar: linear-gradient(to right, #54bafd 0%, #3d98a3 50%, #708b0b 100%);
+
+//   // Logo colors
+//   --bgcolor-logo: var(--primary);
+//   --fillcolor-logo-mark: hsl(var(--bgcolor-navbar-h),calc(var(--bgcolor-navbar-s) - 10%),calc(var(--bgcolor-navbar-l) + 15%));
+
+//   // Sidebar
+//   --bgcolor-sidebar: var(--primary);
+//   --bgcolor-sidebar-hs: var(--primary-hs);
+//   --bgcolor-sidebar-l: var(--primary-l);
+
+//   // --bgcolor-sidebar-nav-item-active: rgba(#, 0.37); // optional
+//   --text-shadow-sidebar-nav-item-active: 0px 0px 10px #0099ff; // optional
+
+//   // Sidebar resize button
+//   --color-resize-button: var(--color-reversal);
+//   --bgcolor-resize-button: hsl(var(--bgcolor-resize-button-hs),var(--bgcolor-resize-button-l));
+//   --bgcolor-resize-button-hs: 199,74%;
+//   --bgcolor-resize-button-l: 49%;
+//   --color-resize-button-hover: var(--color-reversal);
+//   --bgcolor-resize-button-hover: #{hsl.lighten(var(--bgcolor-resize-button), 5%)};
+
+//   // Sidebar contents
+//   --color-sidebar-context: var(--color-global);
+//   --color-sidebar-context-hs: var(--color-global-hs);
+//   --color-sidebar-context-l: var(--color-global-l);
+//   --bgcolor-sidebar-context: hsl(var(--bgcolor-sidebar-context-hs),var(--bgcolor-sidebar-context-l));
+//   --bgcolor-sidebar-context-hs: 193,100%;
+//   --bgcolor-sidebar-context-l: 97%;
+
+//   // Sidebar list group
+//   // --bgcolor-sidebar-list-group: #; // optional
+
+//   // Subnavigation
+//   --bgcolor-subnav: hsl(var(--bgcolor-subnav-hs),var(--bgcolor-subnav-l));
+//   --bgcolor-subnav-hs: var(--bgcolor-global-hs);
+//   --bgcolor-subnav-l: calc(var(--bgcolor-global-l) - 3%);
+
+//   // Icon colors
+//   --color-editor-icons: var(--color-global);
+
+//   // Border colors
+//   --border-color-theme: var(--accentcolor);
+//   --bordercolor-inline-code: #ccc8c8; // optional
+
+//   // admin theme box
+//   --color-theme-color-box: #{hsl.lighten(var(--primary), 20%)};
+
+//   // Navs {
+//   .nav-tabs {
+//     border-bottom: var(--accentcolor) 1px solid;
+//     .nav-link {
+//       &:hover {
+//         border-color: #{hsl.lighten(var(--accentcolor),10%)};
+//         border-bottom: none;
+//       }
+//       &.active {
+//         background-color: transparent;
+//       }
+//     }
+//   }
+//   // Button
+//   .btn-group.grw-page-editor-mode-manager {
+//     .btn.btn-outline-primary {
+//       @include page-editor-mode-manager.btn-page-editor-mode-manager(var(--primary), #{hsl.lighten(var(--primary), 65%)}, #{hsl.lighten(var(--primary), 70%)});
+//     }
+//   }
+// }
+
+// :root[data-bs-theme='dark'] {
+//   // Theme colors
+//   --primary: hsl(var(--primary-hs),var(--primary-l)) !important;
+//   --primary-hs: 197,100%;
+//   --primary-l: 39%;
+//   --secondary: hsl(var(--secondary-hs),var(--secondary-l)) !important;
+//   --secondary-hs: 208,7%;
+//   --secondary-l: 46%;
+//   --accentcolor: hsl(var(--accentcolor-hs),var(--accentcolor-l));
+//   --accentcolor-hs: 203,78%;
+//   --accentcolor-l: 35%;
+
+//   // Background colors
+//   --bgcolor-global: hsl(var(--bgcolor-global-hs),var(--bgcolor-global-l));
+//   --bgcolor-global-hs: 203,77%;
+//   --bgcolor-global-l: 10%;
+//   --bgcolor-navbar: hsl(var(--bgcolor-navbar-hs),var(--bgcolor-navbar-l));
+//   --bgcolor-navbar-hs: 201,20%;
+//   --bgcolor-navbar-l: 19%;
+//   --bgcolor-inline-code: #1f1f22; //optional
+//   --bgcolor-card: #{hsl.darken(var(--bgcolor-global), 5%)};
+//   --bgcolor-blinked-section: #{hsl.alpha(var(--primary),50%)};
+//   --bgcolor-keyword-highlighted: #{darken(var.$grw-marker-red, 30%)};
+
+//   // Font colors
+//   --color-global: hsl(var(--color-global-hs),var(--color-global-l));
+//   --color-global-hs: 180,1%;
+//   --color-global-l: 83%;
+//   --color-reversal: #{bs.$gray-100};
+//   --color-link: hsl(var(--color-link-hs),var(--color-link-l));
+//   --color-link-hs: 201,75%;
+//   --color-link-l: 77%;
+//   --color-link-hover: #{hsl.darken(var(--color-link), 12%)};
+//   --color-link-wiki: #{hsl.lighten(var(--primary),20%)};
+//   --color-link-wiki-hs: var(--primary-hs);
+//   --color-link-wiki-l: calc(var(--primary-l) + 20%);
+//   --color-link-wiki-hover: #{hsl.lighten(var(--primary),40%)};
+//   --color-link-nabvar: var(--color-reversal);
+//   --color-inline-code: #c7254e; // optional
+//   --color-search: #000102;
+
+//   // List Group colors
+//   // --color-list: var(--color-global);
+//   --bgcolor-list: transparent;
+//   --color-list-hover: #16617d;
+//   // --bgcolor-list-hover: #{hsl.lighten(var(--bgcolor-global),3%)}; // optional
+//   // --color-list-active: var(--color-reversal);
+//   // --bgcolor-list-active: var(--primary);
+
+//   // Navbar
+//   --bgcolor-navbar: hsl(var(--bgcolor-navbar-hs),var(--bgcolor-navbar-l));
+//   --bgcolor-navbar-h: 0;
+//   --bgcolor-navbar-s: 1%;
+//   --bgcolor-navbar-l: 16%;
+//   --bgcolor-navbar-hs:var(--bgcolor-navbar-h),var(--bgcolor-navbar-s);
+//   --bgcolor-search-top-dropdown: var(--primary);
+//   --bgcolor-search-top-dropdown-hs: var(--primary-hs);
+//   --bgcolor-search-top-dropdown-l: var(--primary-l);
+//   --border-image-navbar: linear-gradient(to right, #54bafd 0%, #3d98a3 50%, #708b0b 100%);
+
+//   // Logo colors
+//   --bgcolor-logo: #13191c;
+//   --fillcolor-logo-mark: hsl(var(--bgcolor-navbar-h),calc(var(--bgcolor-navbar-s) - 10%),calc(var(--bgcolor-navbar-l) + 15%));
+//   // --fillcolor-logo-mark: #4e5a60;
+
+//   // Sidebar
+//   --bgcolor-sidebar: hsl(var(--bgcolor-sidebar-hs),var(--bgcolor-sidebar-l));
+//   --bgcolor-sidebar-hs: 196,70%;
+//   --bgcolor-sidebar-l: 29%;
+//   // --bgcolor-sidebar-nav-item-active: rgba(#, 0.3); // optional
+//   --text-shadow-sidebar-nav-item-active: 0px 0px 10px #0099ff; // optional
+
+//   // Sidebar resize button
+//   --color-resize-button: var(--color-global);
+//   --bgcolor-resize-button: var(--primary);
+//   --bgcolor-resize-button-hs: var(--primary-hs);
+//   --bgcolor-resize-button-l: var(--primary-l);
+//   --color-resize-button-hover: var(--color-global);
+//   --bgcolor-resize-button-hover: #{hsl.darken(var(--primary), 5%)};
+
+//   // Sidebar contents
+//   --bgcolor-sidebar-context: #{hsl.darken(var(--bgcolor-sidebar), 13%)};
+//   --bgcolor-sidebar-context-hs: var(--bgcolor-sidebar-hs);
+//   --bgcolor-sidebar-context-l: calc(var(--bgcolor-sidebar-l) - 13%);
+//   --color-sidebar-context: var(--color-global);
+//   --color-sidebar-context-hs: var(--color-global-hs);
+//   --color-sidebar-context-l: var(--color-global-l);
+
+//   // Sidebar list group
+//   // --bgcolor-sidebar-list-group: #; // optional
+
+//   // Subnavigation
+//   --bgcolor-subnav: hsl(var(--bgcolor-subnav-hs),var(--bgcolor-subnav-l));
+//   --bgcolor-subnav-hs: var(--bgcolor-global-hs);
+//   --bgcolor-subnav-l: calc(var(--bgcolor-global-l) - 3%);
+
+//   // Icon colors
+//   --color-editor-icons: var(--color-global);
+
+//   // Border colors
+//   --border-color-theme: var(--accentcolor);
+//   --bordercolor-inline-code: #4d4d4d; // optional
+
+//   // admin theme box
+//   --color-theme-color-box: var(--primary);
+
+//   // Navs
+//   .nav-tabs {
+//     border-bottom: var(--accentcolor) 1px solid;
+//     .nav-link {
+//       &:hover {
+//         border-color: #{hsl.lighten(var(--accentcolor), 10%)};
+//         border-bottom: none;
+//       }
+//       &.active {
+//         color: var(--color-link);
+//         background-color: transparent;
+//         border-color: var(--accentcolor);
+//       }
+//     }
+//   }
+
+//   // Table
+//   .table {
+//     color: white;
+//   }
+
+//   // Button
+//   .btn-group.grw-page-editor-mode-manager {
+//     .btn.btn-outline-primary {
+//       @include page-editor-mode-manager.btn-page-editor-mode-manager(#{hsl.lighten(var(--primary), 30%)}, var(--primary), #{hsl.darken(var(--primary), 10%)}, #{hsl.darken(var(--primary), 20%)});
+//     }
+//   }
+// }

+ 31 - 29
packages/preset-themes/vite.themes.config.ts

@@ -1,35 +1,37 @@
 import { defineConfig } from 'vite';
 import { defineConfig } from 'vite';
 
 
-const isProd = process.env.NODE_ENV === 'production';
-
 // https://vitejs.dev/config/
 // https://vitejs.dev/config/
-export default defineConfig({
-  build: {
-    outDir: 'dist/themes',
-    manifest: true,
-    rollupOptions: {
-      input: [
-        '/src/styles/antarctic.scss',
-        '/src/styles/blackboard.scss',
-        '/src/styles/christmas.scss',
-        '/src/styles/default.scss',
-        '/src/styles/fire-red.scss',
-        '/src/styles/future.scss',
-        '/src/styles/halloween.scss',
-        '/src/styles/hufflepuff.scss',
-        '/src/styles/island.scss',
-        '/src/styles/jade-green.scss',
-        '/src/styles/kibela.scss',
-        '/src/styles/mono-blue.scss',
-        '/src/styles/nature.scss',
-        '/src/styles/spring.scss',
-        '/src/styles/wood.scss',
-      ],
-      output: {
-        assetFileNames: isProd
-          ? undefined
-          : 'assets/[name].[ext]', // not attach hash
+export default defineConfig(({ mode }) => {
+  const isProd = mode === 'production';
+
+  return {
+    build: {
+      outDir: 'dist/themes',
+      manifest: true,
+      rollupOptions: {
+        input: [
+          // '/src/styles/antarctic.scss',
+          // '/src/styles/blackboard.scss',
+          // '/src/styles/christmas.scss',
+          '/src/styles/default.scss',
+          // '/src/styles/fire-red.scss',
+          // '/src/styles/future.scss',
+          // '/src/styles/halloween.scss',
+          // '/src/styles/hufflepuff.scss',
+          // '/src/styles/island.scss',
+          // '/src/styles/jade-green.scss',
+          // '/src/styles/kibela.scss',
+          '/src/styles/mono-blue.scss',
+          // '/src/styles/nature.scss',
+          // '/src/styles/spring.scss',
+          // '/src/styles/wood.scss',
+        ],
+        output: {
+          assetFileNames: isProd
+            ? undefined
+            : 'assets/[name].[ext]', // not attach hash
+        },
       },
       },
     },
     },
-  },
+  };
 });
 });

+ 2 - 1
turbo.json

@@ -42,7 +42,8 @@
     "@growi/app#styles-prebuilt": {
     "@growi/app#styles-prebuilt": {
       "outputs": ["src/styles/prebuilt/**"],
       "outputs": ["src/styles/prebuilt/**"],
       "inputs": [
       "inputs": [
-        "src/styles/**/*.scss"
+        "src/styles/**/*.scss",
+        "../../packages/core/scss/**/*.scss"
       ],
       ],
       "outputMode": "new-only"
       "outputMode": "new-only"
     },
     },