- @for (item of toolbar; track item.id) {
-
+
@if (showCode()) {
diff --git a/src/app/features/project-editor/components/html-editor/marketplace-html-editor.component.scss b/src/app/features/project-editor/components/html-editor/marketplace-html-editor.component.scss
index fd78843..850515d 100644
--- a/src/app/features/project-editor/components/html-editor/marketplace-html-editor.component.scss
+++ b/src/app/features/project-editor/components/html-editor/marketplace-html-editor.component.scss
@@ -7,9 +7,54 @@
.html-editor-toolbar {
display: flex;
flex-wrap: wrap;
- gap: 0.25rem;
+ align-items: center;
+ gap: 8px;
+ padding: 6px;
+ border: 1px solid var(--border-color, #d3dad9);
+ border-bottom: none;
+ border-radius: var(--radius-sm) var(--radius-sm) 0 0;
+ background: var(--bg-secondary, #f7f8f8);
}
+.html-editor-toolbar__group {
+ display: flex;
+ gap: 2px;
+
+ & + .html-editor-toolbar__group:not(.html-editor-toolbar__group--end) {
+ padding-left: 8px;
+ border-left: 1px solid var(--border-color, #d3dad9);
+ }
+}
+
+.html-editor-toolbar__group--end {
+ margin-left: auto;
+}
+
+.html-editor-toolbar__btn {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 30px;
+ height: 30px;
+ padding: 0 6px;
+ border: none;
+ border-radius: var(--radius-sm);
+ background: transparent;
+ color: var(--text-primary, #1e3c38);
+ font-size: 0.85rem;
+ cursor: pointer;
+
+ .pi { font-size: 0.85rem; }
+
+ &:hover { background: var(--bg-tertiary, #e8ecea); }
+ &:focus-visible { outline: 2px solid var(--color-primary, #2f8f5b); outline-offset: 1px; }
+}
+
+.html-editor-toolbar__btn--bold { font-weight: 700; }
+.html-editor-toolbar__btn--italic { font-style: italic; font-family: serif; }
+.html-editor-toolbar__btn--underline { text-decoration: underline; }
+.html-editor-toolbar__btn--wide { padding: 0 10px; font-size: 0.8rem; color: var(--text-secondary, #6b7280); }
+
.html-editor-surface {
min-height: 160px;
border: 1px solid var(--border, #ccc);
diff --git a/src/app/features/project-editor/components/html-editor/marketplace-html-editor.component.ts b/src/app/features/project-editor/components/html-editor/marketplace-html-editor.component.ts
index 6b236cb..2f4f41e 100644
--- a/src/app/features/project-editor/components/html-editor/marketplace-html-editor.component.ts
+++ b/src/app/features/project-editor/components/html-editor/marketplace-html-editor.component.ts
@@ -9,22 +9,35 @@ export interface HtmlEditorToolbarCommand {
label: string;
command: string;
value?: string;
+ /** PrimeIcons class (e.g. 'pi-list'); when set the icon renders instead of the label. */
+ icon?: string;
+ /** i18n key for the tooltip/aria-label. */
+ titleKey?: string;
}
export const HTML_EDITOR_TOOLBAR: HtmlEditorToolbarCommand[] = [
- { id: 'bold', label: 'B', command: 'bold' },
- { id: 'italic', label: 'I', command: 'italic' },
- { id: 'underline', label: 'U', command: 'underline' },
- { id: 'h2', label: 'H2', command: 'formatBlock', value: 'H2' },
- { id: 'h3', label: 'H3', command: 'formatBlock', value: 'H3' },
- { id: 'ul', label: 'List', command: 'insertUnorderedList' },
- { id: 'ol', label: '1,2,3', command: 'insertOrderedList' },
- { id: 'link', label: 'Link', command: 'createLink' },
- { id: 'image', label: 'Image', command: 'insertImage' },
- { id: 'table', label: 'Table', command: 'insertHTML', value: '
' },
- { id: 'hr', label: 'HR', command: 'insertHorizontalRule' },
- { id: 'codeblock', label: 'Code', command: 'formatBlock', value: 'PRE' },
- { id: 'embed', label: 'Embed', command: 'insertEmbed' },
+ { id: 'bold', label: 'B', command: 'bold', titleKey: 'builder.htmlToolBold' },
+ { id: 'italic', label: 'I', command: 'italic', titleKey: 'builder.htmlToolItalic' },
+ { id: 'underline', label: 'U', command: 'underline', titleKey: 'builder.htmlToolUnderline' },
+ { id: 'h2', label: 'H2', command: 'formatBlock', value: 'H2', titleKey: 'builder.htmlToolHeading' },
+ { id: 'h3', label: 'H3', command: 'formatBlock', value: 'H3', titleKey: 'builder.htmlToolSubheading' },
+ { id: 'ul', label: '', icon: 'pi-list', command: 'insertUnorderedList', titleKey: 'builder.htmlToolBulletList' },
+ { id: 'ol', label: '1.', command: 'insertOrderedList', titleKey: 'builder.htmlToolNumberedList' },
+ { id: 'link', label: '', icon: 'pi-link', command: 'createLink', titleKey: 'builder.htmlToolLink' },
+ { id: 'image', label: '', icon: 'pi-image', command: 'insertImage', titleKey: 'builder.htmlToolImage' },
+ { id: 'table', label: '', icon: 'pi-table', command: 'insertHTML', value: '
', titleKey: 'builder.htmlToolTable' },
+ { id: 'hr', label: '', icon: 'pi-minus', command: 'insertHorizontalRule', titleKey: 'builder.htmlToolDivider' },
+ { id: 'codeblock', label: '', icon: 'pi-code', command: 'formatBlock', value: 'PRE', titleKey: 'builder.htmlToolCodeBlock' },
+ { id: 'embed', label: '', icon: 'pi-video', command: 'insertEmbed', titleKey: 'builder.htmlToolEmbed' },
+];
+
+/** Visual grouping for the toolbar: text style | headings | lists | insert | advanced. */
+export const HTML_EDITOR_TOOLBAR_GROUPS: string[][] = [
+ ['bold', 'italic', 'underline'],
+ ['h2', 'h3'],
+ ['ul', 'ol'],
+ ['link', 'image', 'table', 'hr'],
+ ['codeblock', 'embed'],
];
@Component({
@@ -43,6 +56,9 @@ export class MarketplaceHtmlEditorComponent implements OnChanges, AfterViewInit
@ViewChild('surface', { static: true }) surface!: ElementRef
;
readonly toolbar = HTML_EDITOR_TOOLBAR;
+ readonly toolbarGroups = HTML_EDITOR_TOOLBAR_GROUPS.map(group =>
+ group.map(id => HTML_EDITOR_TOOLBAR.find(item => item.id === id)!).filter(Boolean)
+ );
readonly showCode = signal(false);
readonly codeValue = signal('');
readonly codeError = signal(null);
diff --git a/src/app/i18n/en.ts b/src/app/i18n/en.ts
index 347ab34..aa60274 100644
--- a/src/app/i18n/en.ts
+++ b/src/app/i18n/en.ts
@@ -687,6 +687,19 @@ export const en: Translations = {
linkVisibleDesc: 'Whether this navigation link is shown to shoppers.',
appName: 'Marketplace Builder',
backToDashboard: 'Back to dashboard',
+ htmlToolBold: 'Bold',
+ htmlToolItalic: 'Italic',
+ htmlToolUnderline: 'Underline',
+ htmlToolHeading: 'Heading',
+ htmlToolSubheading: 'Subheading',
+ htmlToolBulletList: 'Bulleted list',
+ htmlToolNumberedList: 'Numbered list',
+ htmlToolLink: 'Insert link',
+ htmlToolImage: 'Insert image',
+ htmlToolTable: 'Insert table',
+ htmlToolDivider: 'Divider line',
+ htmlToolCodeBlock: 'Code block',
+ htmlToolEmbed: 'Embed video',
breadcrumbRoot: 'Marketplace Builder',
statusComplete: 'Complete',
statusInProgress: 'In progress',
diff --git a/src/app/i18n/hy.ts b/src/app/i18n/hy.ts
index 130dda0..427646b 100644
--- a/src/app/i18n/hy.ts
+++ b/src/app/i18n/hy.ts
@@ -687,6 +687,19 @@ export const hy: Translations = {
linkVisibleDesc: 'Արդյո՞ք այս նավիգացիոն հղումը ցուցադրվում է գնորդներին։',
appName: 'Մարկետփլեյսի կոնստրուկտոր',
backToDashboard: 'Վերադառնալ կառավարման վահանակ',
+ htmlToolBold: 'Թավ',
+ htmlToolItalic: 'Շեղ',
+ htmlToolUnderline: 'Ընդգծված',
+ htmlToolHeading: 'Վերնագիր',
+ htmlToolSubheading: 'Ենթավերնագիր',
+ htmlToolBulletList: 'Կետային ցուցակ',
+ htmlToolNumberedList: 'Համարակալված ցուցակ',
+ htmlToolLink: 'Տեղադրել հղում',
+ htmlToolImage: 'Տեղադրել նկար',
+ htmlToolTable: 'Տեղադրել աղյուսակ',
+ htmlToolDivider: 'Բաժանարար գիծ',
+ htmlToolCodeBlock: 'Կոդի բլոկ',
+ htmlToolEmbed: 'Ներդնել տեսանյութ',
breadcrumbRoot: 'Մարկետփլեյսի կոնստրուկտոր',
statusComplete: 'Ավարտված',
statusInProgress: 'Ընթացքի մեջ',
diff --git a/src/app/i18n/ru.ts b/src/app/i18n/ru.ts
index 0840872..e5f93e1 100644
--- a/src/app/i18n/ru.ts
+++ b/src/app/i18n/ru.ts
@@ -687,6 +687,19 @@ export const ru: Translations = {
linkVisibleDesc: 'Показывать ли эту ссылку навигации покупателям.',
appName: 'Конструктор маркетплейса',
backToDashboard: 'Назад в панель управления',
+ htmlToolBold: 'Жирный',
+ htmlToolItalic: 'Курсив',
+ htmlToolUnderline: 'Подчёркнутый',
+ htmlToolHeading: 'Заголовок',
+ htmlToolSubheading: 'Подзаголовок',
+ htmlToolBulletList: 'Маркированный список',
+ htmlToolNumberedList: 'Нумерованный список',
+ htmlToolLink: 'Вставить ссылку',
+ htmlToolImage: 'Вставить изображение',
+ htmlToolTable: 'Вставить таблицу',
+ htmlToolDivider: 'Разделительная линия',
+ htmlToolCodeBlock: 'Блок кода',
+ htmlToolEmbed: 'Встроить видео',
breadcrumbRoot: 'Конструктор маркетплейса',
statusComplete: 'Готово',
statusInProgress: 'В процессе',
diff --git a/src/app/i18n/translations.ts b/src/app/i18n/translations.ts
index 9843855..c9edf5a 100644
--- a/src/app/i18n/translations.ts
+++ b/src/app/i18n/translations.ts
@@ -685,6 +685,20 @@ export interface Translations {
linkVisibleDesc: string;
appName: string;
backToDashboard: string;
+ htmlToolBold: string;
+ htmlToolItalic: string;
+ htmlToolUnderline: string;
+ htmlToolHeading: string;
+ htmlToolSubheading: string;
+ htmlToolBulletList: string;
+ htmlToolNumberedList: string;
+ htmlToolLink: string;
+ htmlToolImage: string;
+ htmlToolTable: string;
+ htmlToolDivider: string;
+ htmlToolCodeBlock: string;
+ htmlToolEmbed: string;
+
breadcrumbRoot: string;
statusComplete: string;
statusInProgress: string;