feat: Add RTL support in public help center (#11692)
# Pull Request Template ## Description This PR adds RTL support in public help center. Fixes https://linear.app/chatwoot/issue/CW-4459/support-for-rtl-in-public-help-center ## Type of change - [x] New feature (non-breaking change which adds functionality) ## How Has This Been Tested? ### Loom video https://www.loom.com/share/d48a26ec80e04545addca825882b4d79?sid=aa7a6b37-33bc-4f63-b1cc-54b27a7733cf ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
// scss-lint:disable SpaceAfterPropertyColon
|
||||||
@import 'tailwindcss/base';
|
@import 'tailwindcss/base';
|
||||||
@import 'tailwindcss/components';
|
@import 'tailwindcss/components';
|
||||||
@import 'tailwindcss/utilities';
|
@import 'tailwindcss/utilities';
|
||||||
@@ -7,7 +8,21 @@
|
|||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
font-family: 'InterDisplay', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
|
font-family:
|
||||||
|
'InterDisplay',
|
||||||
|
-apple-system,
|
||||||
|
system-ui,
|
||||||
|
BlinkMacSystemFont,
|
||||||
|
'Segoe UI',
|
||||||
|
Roboto,
|
||||||
|
'Helvetica Neue',
|
||||||
|
Tahoma,
|
||||||
|
Arial,
|
||||||
|
sans-serif,
|
||||||
|
'Noto Sans',
|
||||||
|
'Apple Color Emoji',
|
||||||
|
'Segoe UI Emoji',
|
||||||
|
'Noto Color Emoji';
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export default {
|
|||||||
}
|
}
|
||||||
if (el.tag === 'h2') {
|
if (el.tag === 'h2') {
|
||||||
if (this.h1Count > 0) {
|
if (this.h1Count > 0) {
|
||||||
return 'ml-2';
|
return 'ltr:ml-2 rtl:mr-2';
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ export default {
|
|||||||
if (!this.h1Count && !this.h2Count) {
|
if (!this.h1Count && !this.h2Count) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return 'ml-5';
|
return 'ltr:ml-5 rtl:mr-5';
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
@@ -94,17 +94,19 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="hidden lg:block flex-1 py-6 scroll-mt-24 pl-4 sticky top-24">
|
<div
|
||||||
|
class="hidden lg:block flex-1 py-6 scroll-mt-24 ltr:pl-4 rtl:pr-4 sticky top-24"
|
||||||
|
>
|
||||||
<div v-if="rows.length > 0" class="py-2 overflow-auto">
|
<div v-if="rows.length > 0" class="py-2 overflow-auto">
|
||||||
<nav class="max-w-2xl">
|
<nav class="max-w-2xl">
|
||||||
<ol
|
<ol
|
||||||
role="list"
|
role="list"
|
||||||
class="flex flex-col gap-2 text-base border-l-2 border-solid border-slate-100 dark:border-slate-800"
|
class="flex flex-col gap-2 text-base ltr:border-l-2 rtl:border-r-2 border-solid border-slate-100 dark:border-slate-800"
|
||||||
>
|
>
|
||||||
<li
|
<li
|
||||||
v-for="element in rows"
|
v-for="element in rows"
|
||||||
:key="element.slug"
|
:key="element.slug"
|
||||||
class="leading-6 border-l-2 relative -left-0.5 border-solid"
|
class="leading-6 ltr:border-l-2 rtl:border-r-2 relative ltr:-left-0.5 rtl:-right-0.5 border-solid"
|
||||||
:class="elementBorderStyles(element)"
|
:class="elementBorderStyles(element)"
|
||||||
>
|
>
|
||||||
<p class="py-1 px-3" :class="getClassName(element)">
|
<p class="py-1 px-3" :class="getClassName(element)">
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import slugifyWithCounter from '@sindresorhus/slugify';
|
|||||||
import PublicArticleSearch from './components/PublicArticleSearch.vue';
|
import PublicArticleSearch from './components/PublicArticleSearch.vue';
|
||||||
import TableOfContents from './components/TableOfContents.vue';
|
import TableOfContents from './components/TableOfContents.vue';
|
||||||
import { initializeTheme } from './portalThemeHelper.js';
|
import { initializeTheme } from './portalThemeHelper.js';
|
||||||
|
import { getLanguageDirection } from 'dashboard/components/widgets/conversation/advancedFilterItems/languages.js';
|
||||||
|
|
||||||
export const getHeadingsfromTheArticle = () => {
|
export const getHeadingsfromTheArticle = () => {
|
||||||
const rows = [];
|
const rows = [];
|
||||||
@@ -114,10 +115,19 @@ export const InitializationHelpers = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setDirectionAttribute: () => {
|
||||||
|
const portalElement = document.getElementById('portal');
|
||||||
|
if (!portalElement) return;
|
||||||
|
|
||||||
|
const locale = document.querySelector('.locale-switcher')?.value;
|
||||||
|
portalElement.dir = locale && getLanguageDirection(locale) ? 'rtl' : 'ltr';
|
||||||
|
},
|
||||||
|
|
||||||
initializeThemesInPortal: initializeTheme,
|
initializeThemesInPortal: initializeTheme,
|
||||||
|
|
||||||
initialize: () => {
|
initialize: () => {
|
||||||
openExternalLinksInNewTab();
|
openExternalLinksInNewTab();
|
||||||
|
InitializationHelpers.setDirectionAttribute();
|
||||||
if (window.portalConfig.isPlainLayoutEnabled === 'true') {
|
if (window.portalConfig.isPlainLayoutEnabled === 'true') {
|
||||||
InitializationHelpers.appendPlainParamToURLs();
|
InitializationHelpers.appendPlainParamToURLs();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<% author_count = category.articles.published.order(position: :asc).map(&:author).uniq.size %>
|
<% author_count = category.articles.published.order(position: :asc).map(&:author).uniq.size %>
|
||||||
<% if author_count > 0 %>
|
<% if author_count > 0 %>
|
||||||
<div class="flex flex-row items-center gap-1">
|
<div class="flex flex-row items-center gap-1">
|
||||||
<div class="flex flex-row items-center -space-x-2">
|
<div class="flex items-center ltr:flex-row rtl:flex-row-reverse -space-x-2">
|
||||||
<% category.articles.published.order(position: :asc).map(&:author).uniq.take(3).each do |author| %>
|
<% category.articles.published.order(position: :asc).map(&:author).uniq.take(3).each do |author| %>
|
||||||
<%= render "public/api/v1/portals/thumbnail", author: author, size: 5 %>
|
<%= render "public/api/v1/portals/thumbnail", author: author, size: 5 %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<% first_author = category.articles.published.order(position: :asc).map(&:author).uniq.first&.name || '' %>
|
<% first_author = category.articles.published.order(position: :asc).map(&:author).uniq.first&.name || '' %>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<div class="flex items-center w-full py-5 overflow-hidden">
|
<div class="flex items-center w-full py-5 overflow-hidden">
|
||||||
<a href="<%= generate_home_link(@portal.slug, @portal.config['default_locale'] || params[:locale], @theme_from_params, @is_plain_layout_enabled) %>" class="flex items-center h-10 text-lg font-semibold text-slate-900 dark:text-white">
|
<a href="<%= generate_home_link(@portal.slug, @portal.config['default_locale'] || params[:locale], @theme_from_params, @is_plain_layout_enabled) %>" class="flex items-center h-10 text-lg font-semibold text-slate-900 dark:text-white">
|
||||||
<% if @portal.logo.present? %>
|
<% if @portal.logo.present? %>
|
||||||
<img src="<%= url_for(@portal.logo) %>" class="w-auto h-10 mr-2" />
|
<img src="<%= url_for(@portal.logo) %>" class="w-auto h-10 ltr:mr-2 rtl:ml-2" />
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= @portal.name %>
|
<%= @portal.name %>
|
||||||
</a>
|
</a>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<%# Go to homepage link section %>
|
<%# Go to homepage link section %>
|
||||||
<div class="flex items-center justify-between gap-2 sm:gap-5">
|
<div class="flex items-center justify-between gap-2 sm:gap-5">
|
||||||
<% if @portal.homepage_link %>
|
<% if @portal.homepage_link %>
|
||||||
<div class="hidden px-1 py-2 ml-8 cursor-pointer border-l-1 border-slate-50 dark:border-slate-800 md:block">
|
<div class="hidden px-1 py-2 ltr:ml-8 rtl:mr-8 cursor-pointer md:block">
|
||||||
<div class="flex-grow flex-shrink-0">
|
<div class="flex-grow flex-shrink-0">
|
||||||
<a id="header-action-button" target="_blank" rel="noopener noreferrer nofollow" href="<%= @portal.homepage_link %>" class="flex flex-row items-center gap-1 text-sm font-medium whitespace-nowrap text-slate-800 dark:text-slate-100 stroke-slate-700 dark:stroke-slate-200">
|
<a id="header-action-button" target="_blank" rel="noopener noreferrer nofollow" href="<%= @portal.homepage_link %>" class="flex flex-row items-center gap-1 text-sm font-medium whitespace-nowrap text-slate-800 dark:text-slate-100 stroke-slate-700 dark:stroke-slate-200">
|
||||||
<%= render partial: 'icons/redirect' %>
|
<%= render partial: 'icons/redirect' %>
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<%# Appearance dropdown section %>
|
<%# Appearance dropdown section %>
|
||||||
<div id="appearance-dropdown" data-current-theme="<%= @theme_from_params %>" class="absolute flex-col w-32 h-auto bg-white border border-solid rounded dark:bg-slate-900 top-9 right-1 border-slate-100 dark:border-slate-800" aria-hidden="true" style="display: none;" data-dropdown="appearance-dropdown">
|
<div id="appearance-dropdown" data-current-theme="<%= @theme_from_params %>" class="absolute flex-col w-32 h-auto bg-white border border-solid rounded dark:bg-slate-900 top-9 ltr:right-1 rtl:left-1 border-slate-100 dark:border-slate-800" aria-hidden="true" style="display: none;" data-dropdown="appearance-dropdown">
|
||||||
<button id="toggle-theme-button" data-theme="system" class="flex flex-row items-center justify-between gap-1 px-2 py-2 border-b border-solid border-slate-100 dark:border-slate-800 stroke-slate-700 dark:stroke-slate-200 text-slate-800 dark:text-slate-100">
|
<button id="toggle-theme-button" data-theme="system" class="flex flex-row items-center justify-between gap-1 px-2 py-2 border-b border-solid border-slate-100 dark:border-slate-800 stroke-slate-700 dark:stroke-slate-200 text-slate-800 dark:text-slate-100">
|
||||||
<div class="flex flex-row items-center gap-1">
|
<div class="flex flex-row items-center gap-1">
|
||||||
<%= render partial: 'icons/monitor' %>
|
<%= render partial: 'icons/monitor' %>
|
||||||
|
|||||||
Reference in New Issue
Block a user