diff --git a/services/web/frontend/js/shared/components/upgrade-benefits.jsx b/services/web/frontend/js/shared/components/upgrade-benefits.jsx
index c0a19d987f..4f8001f7c8 100644
--- a/services/web/frontend/js/shared/components/upgrade-benefits.jsx
+++ b/services/web/frontend/js/shared/components/upgrade-benefits.jsx
@@ -1,39 +1,50 @@
import Icon from './icon'
+import MaterialIcon from '@/shared/components/material-icon'
+import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
import { useTranslation } from 'react-i18next'
import { memo } from 'react'
+function Check() {
+ return (
+ }
+ bs5={}
+ />
+ )
+}
+
function UpgradeBenefits() {
const { t } = useTranslation()
return (
-
-
+
{t('unlimited_projects')}
-
-
+
{t('collabs_per_proj', { collabcount: 'Multiple' })}
-
-
+
{t('full_doc_history')}
-
-
+
{t('sync_to_dropbox')}
-
-
+
{t('sync_to_github')}
-
-
+
{t('compile_larger_projects')}
diff --git a/services/web/frontend/stylesheets/bootstrap-5/main-style.scss b/services/web/frontend/stylesheets/bootstrap-5/main-style.scss
index b28275d8f2..c5865ecbec 100644
--- a/services/web/frontend/stylesheets/bootstrap-5/main-style.scss
+++ b/services/web/frontend/stylesheets/bootstrap-5/main-style.scss
@@ -30,3 +30,7 @@
// Page layout that isn't related to a particular component or page
@import 'base/layout';
+
+// Module styles
+// TODO: find a way for modules to add styles dynamically
+@import 'modules/all';
diff --git a/services/web/frontend/stylesheets/bootstrap-5/modules/all.scss b/services/web/frontend/stylesheets/bootstrap-5/modules/all.scss
new file mode 100644
index 0000000000..7e34428eef
--- /dev/null
+++ b/services/web/frontend/stylesheets/bootstrap-5/modules/all.scss
@@ -0,0 +1 @@
+@import 'symbol-palette';
diff --git a/services/web/frontend/stylesheets/bootstrap-5/modules/symbol-palette.scss b/services/web/frontend/stylesheets/bootstrap-5/modules/symbol-palette.scss
new file mode 100644
index 0000000000..dd6d5f64f8
--- /dev/null
+++ b/services/web/frontend/stylesheets/bootstrap-5/modules/symbol-palette.scss
@@ -0,0 +1,207 @@
+:root {
+ --symbol-palette-bg: var(--bg-dark-tertiary);
+ --symbol-palette-color: var(--content-primary-dark);
+ --symbol-palette-header-background: var(--bg-dark-secondary);
+ --symbol-palette-item-bg: var(--bg-dark-secondary);
+ --symbol-palette-item-color: var(--content-primary-dark);
+ --symbol-palette-selected-tab-bg: var(--bg-dark-tertiary);
+ --symbol-palette-selected-tab-color: var(--content-primary-dark);
+ --symbol-palette-text-shadow-color: var(--bg-dark-primary);
+ --symbol-palette-overlay-bg: #{rgb($bg-dark-tertiary, 0.75)};
+}
+
+@include theme('light') {
+ --symbol-palette-bg: var(--bg-light-primary);
+ --symbol-palette-color: var(--content-secondary);
+ --symbol-palette-header-background: var(--bg-light-tertiary);
+ --symbol-palette-item-bg: var(--bg-light-tertiary);
+ --symbol-palette-item-color: var(--content-secondary);
+ --symbol-palette-selected-tab-bg: var(--bg-light-primary);
+ --symbol-palette-selected-tab-color: var(--blue-50);
+ --symbol-palette-text-shadow-color: var(--bg-light-tertiary);
+ --symbol-palette-overlay-bg: #{rgb($bg-light-primary, 0.75)};
+}
+
+.symbol-palette-container {
+ height: 100%;
+ width: 100%;
+ position: relative;
+}
+
+.symbol-palette {
+ display: flex;
+ flex-direction: column;
+ background: var(--symbol-palette-bg);
+ color: var(--symbol-palette-color);
+ width: 100%;
+ height: 100%;
+ min-height: 220px; // allow space for the overlay contents
+}
+
+.symbol-palette-header-outer {
+ flex-shrink: 0;
+ display: flex;
+ flex-wrap: nowrap;
+ justify-content: space-between;
+ align-items: stretch;
+ font-family: $font-family-sans-serif;
+ font-size: var(--font-size-03);
+ background: var(--symbol-palette-header-background);
+ box-shadow: inset 0 1px 0 rgb(255 255 255 / 10%);
+}
+
+.symbol-palette-header {
+ flex: 1;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-items: stretch;
+}
+
+.symbol-palette-tab-list[role='tablist'] {
+ background: none;
+ border-bottom: none;
+ flex-wrap: wrap;
+ display: flex;
+}
+
+.symbol-palette-tab[role='tab'] {
+ appearance: none;
+ background: none;
+ border: none;
+ border-bottom: 1px solid transparent;
+ color: inherit;
+ cursor: pointer;
+ display: inline-block;
+ font: inherit;
+ margin: 0;
+ padding: var(--spacing-02) var(--spacing-04);
+
+ &[aria-selected='true'] {
+ background: var(--symbol-palette-selected-tab-bg);
+ color: var(--symbol-palette-selected-tab-color);
+ }
+
+ &:disabled {
+ cursor: default;
+ opacity: 0.25;
+ }
+}
+
+.symbol-palette-body {
+ flex: 1;
+ overflow-y: auto;
+}
+
+.symbol-palette-items {
+ display: flex;
+ flex-wrap: wrap;
+ padding: var(--spacing-03);
+}
+
+.symbol-palette-item {
+ font-family: 'Stix Two Math', serif;
+ font-size: 24px;
+ line-height: 42px;
+ height: 42px;
+ width: 42px;
+ margin: var(--spacing-03);
+ color: var(--symbol-palette-item-color);
+ background: var(--symbol-palette-item-bg);
+ border: 1px solid transparent;
+ border-radius: var(--border-radius-base);
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.symbol-palette-item-command {
+ font-family: monospace;
+ font-weight: bold;
+}
+
+.symbol-palette-item-notes {
+ margin-top: var(--spacing-03);
+}
+
+.symbol-palette-empty {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: var(--spacing-05);
+}
+
+.symbol-palette-search {
+ padding: var(--spacing-01) var(--spacing-05);
+ margin: var(--spacing-03);
+ line-height: 1;
+ height: auto;
+ width: auto;
+}
+
+.symbol-palette-header-group {
+ display: flex;
+ align-items: stretch;
+ white-space: nowrap;
+ margin-left: var(--spacing-03);
+}
+
+.symbol-palette-info-link,
+.symbol-palette-info-link:focus,
+.symbol-palette-info-link:hover {
+ color: inherit;
+}
+
+.symbol-palette-close-button-outer {
+ display: flex;
+}
+
+.symbol-palette-close-button {
+ --bs-btn-close-color: var(--symbol-palette-color);
+
+ [data-theme='default'] & {
+ filter: var(--bs-btn-close-white-filter);
+ }
+
+ margin-top: var(--spacing-04);
+ margin-left: var(--spacing-05);
+ margin-right: var(--spacing-03);
+
+ .symbol-palette-unavailable & {
+ visibility: hidden;
+ }
+}
+
+.symbol-palette-overlay {
+ position: absolute;
+ inset: 0;
+ background: var(--symbol-palette-overlay-bg);
+ color: var(--symbol-palette-color);
+ display: flex;
+ flex-direction: column;
+ padding: 0 var(--spacing-09) var(--spacing-05);
+ align-items: center;
+ text-shadow: 0 0 8px var(--symbol-palette-text-shadow-color);
+ min-height: 200px;
+ overflow: auto;
+
+ h4 {
+ font-weight: bold;
+ color: var(--symbol-palette-color);
+ text-align: center;
+ }
+
+ .symbol-palette-close-button {
+ position: absolute;
+ top: 0;
+ right: 0;
+ }
+
+ .upgrade-benefits {
+ column-count: 2;
+
+ li {
+ display: flex;
+ }
+ }
+}
diff --git a/services/web/frontend/stylesheets/modules/symbol-palette.less b/services/web/frontend/stylesheets/modules/symbol-palette.less
index fcc168b6c1..d99557bdb7 100644
--- a/services/web/frontend/stylesheets/modules/symbol-palette.less
+++ b/services/web/frontend/stylesheets/modules/symbol-palette.less
@@ -129,9 +129,11 @@
.symbol-palette-close-button {
background: transparent;
+ opacity: 1;
+ float: none;
+ text-shadow: none;
color: @symbol-palette-color;
- padding-left: @padding-sm;
- padding-right: @padding-sm;
+ padding: 4px @padding-sm;
margin-left: @margin-xs;
font-size: 24px;
font-weight: bold;