diff --git a/.gitignore b/.gitignore index 7105f913..e6e7da51 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ node_modules # Generated content /build /storybook-static +/demo/storybook-static diff --git a/demo/src/Components/DocPage/data.ts b/demo/src/Components/DocPage/data.ts index 7a4be2ca..091710a2 100644 --- a/demo/src/Components/DocPage/data.ts +++ b/demo/src/Components/DocPage/data.ts @@ -1,6 +1,7 @@ import {Lang} from '../../../../src'; import pageContentEn from './page-en.json'; +import pageContentHe from './page-he.json'; import pageContentRu from './page-ru.json'; import singlePageContentEn from './single-page-en.json'; import singlePageContentRu from './single-page-ru.json'; @@ -14,6 +15,8 @@ export const getContent = (lang: Lang, singlePage: boolean) => { if (lang === 'ru') { return pageContentRu; + } else if (lang === 'he') { + return pageContentHe; } return pageContentEn; diff --git a/demo/src/Components/DocPage/index.stories.tsx b/demo/src/Components/DocPage/index.stories.tsx index a8e2cecc..0423c4d8 100644 --- a/demo/src/Components/DocPage/index.stories.tsx +++ b/demo/src/Components/DocPage/index.stories.tsx @@ -60,9 +60,24 @@ const useSettings = () => { }; }; +const useDirection = (lang) => { + const [dir, onChangeDir] = useState('ltr'); + + useEffect(() => { + if (lang === 'he') { + onChangeDir('rtl'); + } else { + onChangeDir('ltr'); + } + + document.dir = dir; + }, [lang, dir]); +}; + const useLangs = () => { - const langs = ['ru', 'en', 'cs']; + const langs = ['ru', 'en', 'cs', 'he']; const [lang, onChangeLang] = useState(DEFAULT_SETTINGS.lang); + useDirection(lang); return { lang, diff --git a/demo/src/Components/DocPage/page-he.json b/demo/src/Components/DocPage/page-he.json new file mode 100644 index 00000000..d7ab89aa --- /dev/null +++ b/demo/src/Components/DocPage/page-he.json @@ -0,0 +1,288 @@ +{ + "html": "

לשירותי Yandex.Cloud עשויים להיות מכסות ומגבלות:

\n\n

ניתן לראות את המכסות שנקבעו עבור חשבונך בהנהלה מסוף .

", + "title": "מכסות ומגבלות", + "headings": [ + { + "title": "למה צריך מכסות?", + "href": "#quotas", + "level": 2 + }, + { + "title": "ברירת מחדל מכסות ומגבלות עבור שירותי ענן", + "href": "#quotas-and-limits-defaults-for-yandex.cloud-services", + "level": 2, + "items": [ + { + "title": "Yandex Compute Cloud", + "href": "#compute", + "level": 3, + "items": [] + }, + { + "title": "Yandex Object Storage", + "href": "#storage", + "level": 3, + "items": [] + }, + { + "title": "Yandex Virtual Private Cloud", + "href": "#vpc", + "level": 3, + "items": [] + }, + { + "title": "Yandex Resource Manager", + "href": "#resource-manager", + "level": 3 + }, + { + "title": "Yandex Load Balancer", + "href": "#load-balancer", + "level": 3, + "items": [] + }, + { + "title": "Yandex Managed Service for ClickHouse", + "href": "#mch", + "level": 3, + "items": [] + }, + { + "title": "Yandex Managed Service for MongoDB", + "href": "#mmg", + "level": 3, + "items": [] + }, + { + "title": "Yandex Managed Service for MySQL", + "href": "#mmy", + "level": 3, + "items": [] + }, + { + "title": "Yandex Managed Service for PostgreSQL", + "href": "#mpg", + "level": 3, + "items": [] + }, + { + "title": "Yandex Managed Service for Redis", + "href": "#mrd", + "level": 3, + "items": [] + }, + { + "title": "Yandex Message Queue", + "href": "#mq", + "level": 3, + "items": [] + }, + { + "title": "Yandex SpeechKit", + "href": "#speechkit", + "level": 3, + "items": [] + }, + { + "title": "Yandex Translate", + "href": "#translate", + "level": 3, + "items": [] + }, + { + "title": "Yandex Vision", + "href": "#vision", + "level": 3, + "items": [] + } + ] + } + ], + "meta": { + "author": { + "avatar": "https://avatars.githubusercontent.com/u/2485935?v=4", + "email": "", + "login": "robot-dataui-vcs@yandex-team.ru", + "name": "DataUI VCS Robot", + "url": "http://yandex.ru/" + }, + "contributors": [ + { + "avatar": "https://avatars.githubusercontent.com/u/2485945?v=6", + "email": "robot-dataui-vcs@yandex-team.ru", + "login": "", + "name": "DataUI VCS Robot", + "url": "" + } + ] + }, + "toc": { + "title": "סקירת פלטפורמה", + "href": "/docs/overview/", + "items": [ + { + "name": "שירותי Yandex.Cloud", + "href": "/docs/overview/concepts/services", + "id": "e619422ec28a87ea25c41d4ad7e45563" + }, + { + "name": "השוואה לפלטפורמות אחרות", + "expanded": true, + "items": [ + { + "name": "סקירה", + "href": "/docs/overview/platform-comparison/", + "id": "6cb52f285fd5d6ec04cbd96854dffab6" + }, + { + "name": "להשוות עם Amazon Web Services", + "href": "/docs/overview/platform-comparison/aws", + "id": "1d84cf0e31f3f0968bdc6e8c2e11ba2f" + }, + { + "name": "להשוות עם Google Cloud Platform", + "href": "/docs/overview/platform-comparison/gcp", + "id": "931f7302b4162c44fbe9bb07cea05b1e" + }, + { + "name": "להשוות עם Microsoft Azure", + "href": "/docs/overview/platform-comparison/azure", + "id": "c14b119f6944d57afd8d4b3e61c37e21" + } + ], + "id": "fa5cef5c0b0cf236fdaa1562cbc48eb8" + }, + { + "name": "אזורי זמינות", + "href": "/docs/overview/concepts/geo-scope", + "id": "054328058d7c7b60ff85e3c95be1a264" + }, + { + "name": "תחילת העבודה", + "href": "/docs/overview/quickstart", + "id": "c984893c04c28bc3fe91f5ff87b79c29" + }, + { + "name": "שלבי מוכנות השירות", + "href": "/docs/overview/concepts/launch-stages", + "id": "c53a86addb3cf17f0847acde5282ad84" + }, + { + "name": "מכסות ומגבלות", + "href": "/docs/overview/concepts/quotas-limits", + "id": "56baa37ef41a57f75c4fce09722ab06c" + }, + { + "name": "API", + "href": "/docs/overview/api", + "id": "136bdc27253376a450eee99e4539c186" + }, + { + "name": "בטיחות ותאימות", + "items": [ + { + "name": "המלצות אבטחה", + "href": "/docs/overview/security-bulletins/", + "id": "c87ac8d995548646dec5661b1b28e45c" + }, + { + "name": "כללים לביצוע סריקות אבטחה חיצוניות", + "href": "/docs/overview/compliance/pentest", + "id": "544f4d243ace1fc32591d87d2460742d" + }, + { + "name": "אבטחת פלטפורמת Yandex.Cloud", + "items": [ + { + "name": "סקירה", + "href": "/docs/overview/security/", + "id": "022cc6311c43fdd3c2848a238c92de1e" + }, + { + "name": "עקרונות בטיחות מרכזיים", + "href": "/docs/overview/security/principles", + "id": "fba46ca0333fec72f16d0e29fb78e239", + "names": [ + { + "name": "אבטחת פלטפורמת Yandex.Cloud", + "items": [ + { + "name": "סקירה", + "href": "/docs/overview/security/", + "id": "022cc6311c43fdd3c2848a238c92de1e" + }, + { + "name": "עקרונות בטיחות מרכזיים", + "href": "/docs/overview/security/principles", + "id": "fba46ca0333fec72f16d0e29fb78e239" + } + ] + } + ] + }, + { + "name": "שיתוף באחריות לאבטחה", + "href": "/docs/overview/security/respons", + "id": "177e184118e1e45bc890a53bf76971c7" + }, + { + "name": "מעקב אחר שיטות עבודה וסטנדרטים מומלצים", + "href": "/docs/overview/security/standarts", + "id": "778f32125645fc81b0f680d2d9d09d23" + }, + { + "name": "עמידה בדרישות", + "href": "/docs/overview/security/conform", + "id": "4d7329262a479edc4b28a7607a31c2b4" + }, + { + "name": "אמצעי הגנה טכניים בצד הספק", + "href": "/docs/overview/security/tech-measures", + "id": "98cfa650bb690aa5b9a9aa66f3e7e52b" + }, + { + "name": "הגנות זמינות למשתמשי ענן", + "href": "/docs/overview/security/user-side", + "id": "aaffdd260266d59cd003e6fcab17a1ec" + }, + { + "name": "משאבים שימושיים", + "href": "/docs/overview/security/resources", + "id": "72071e3e599234cb4df3fe56ac378dc1" + } + ], + "id": "f8cca556a8df3df325a1dce2ffec52dc" + } + ], + "id": "7f196892c00a04c9d36a10bc2275ccb8" + }, + { + "name": "מחיקת נתוני משתמש", + "href": "/docs/overview/concepts/data-deletion", + "id": "66fe49c2a324ffd44541fe6a33e14ed0" + }, + { + "name": "SLA", + "href": "/docs/overview/sla", + "id": "1636c6203504367fc47f73077e95ebad" + }, + { + "name": "שאלות ותשובות", + "href": "/docs/overview/qa", + "id": "ff7aacc415c714c83d0ea5715eabb016" + } + ] + }, + "breadcrumbs": [ + { + "name": "תיעוד" + }, + { + "name": "מכסות ומגבלות" + } + ], + "filePath": "/cache/c12878f1-cc2e-445f-8f96-7374fe76b074/ru/overview/concepts/quotas-limits.md", + "githubUrl": "https://github.com/yandex-cloud/docs/tree/master/ru/overview/concepts/quotas-limits.md", + "vcsType": "github", + "vcsUrl": "https://github.com/yandex-cloud/docs/tree/master/ru/overview/concepts/quotas-limits.md" +} diff --git a/src/components/Controls/Controls.scss b/src/components/Controls/Controls.scss index 8e1dff20..cb1c6106 100644 --- a/src/components/Controls/Controls.scss +++ b/src/components/Controls/Controls.scss @@ -20,7 +20,6 @@ } &__list-icon { - margin-right: 8px; font-size: 22px; } @@ -28,6 +27,7 @@ --g-focus-border-radius: 4px; display: flex; + gap: 8px; align-items: center; width: 100%; height: 100%; @@ -40,6 +40,10 @@ font-family: inherit; @include focusable(-2px); + + [dir='rtl'] & { + flex-direction: row-reverse; + } } &__icon-rotated { diff --git a/src/components/Controls/single-controls/LangControl.tsx b/src/components/Controls/single-controls/LangControl.tsx index a411782a..e6497afe 100644 --- a/src/components/Controls/single-controls/LangControl.tsx +++ b/src/components/Controls/single-controls/LangControl.tsx @@ -17,11 +17,13 @@ import '../Controls.scss'; const ICONS: Record = { en: '🇬🇧', ru: '🇷🇺', + he: '🇮🇱', }; -const DEFAULT_LANGS = ['en', 'ru']; +const DEFAULT_LANGS = ['en', 'ru', 'he']; const LEGACY_LANG_ITEMS = [ {value: Lang.En, text: 'English', icon: '🇬🇧'}, {value: Lang.Ru, text: 'Русский', icon: '🇷🇺'}, + {value: Lang.He, text: 'Hebrew', icon: '🇮🇱'}, ]; const b = block('dc-controls'); diff --git a/src/components/Controls/single-controls/SettingsControl/SettingsControl.scss b/src/components/Controls/single-controls/SettingsControl/SettingsControl.scss index 3a124e03..c0f0e9ad 100644 --- a/src/components/Controls/single-controls/SettingsControl/SettingsControl.scss +++ b/src/components/Controls/single-controls/SettingsControl/SettingsControl.scss @@ -4,6 +4,10 @@ &__text-size-control { display: flex; align-items: center; + + [dir='rtl'] & { + flex-direction: row-reverse; + } } &__text-size-button { @@ -50,6 +54,10 @@ display: flex; padding: 12px; width: 100%; + + [dir='rtl'] & { + flex-direction: row-reverse; + } } &__list-item-description { @@ -60,6 +68,14 @@ display: flex; align-items: center; margin-left: auto; + + [dir='rtl'] & { + margin: 0 auto 0 0; + } + + [dir='rtl'] & > label { + transform: rotate(180deg); + } } @media (max-width: map-get($screenBreakpoints, 'md')) { diff --git a/src/components/DocPage/DocPage.scss b/src/components/DocPage/DocPage.scss index 55a759bf..036c016b 100644 --- a/src/components/DocPage/DocPage.scss +++ b/src/components/DocPage/DocPage.scss @@ -55,6 +55,11 @@ position: absolute; right: 7px; + [dir='rtl'] & { + flex-direction: row-reverse; + left: -210px; + } + & > .dc-controls { position: fixed; top: calc(6px + var(--dc-header-height, #{$headerHeight})); diff --git a/src/components/Paginator/Paginator.scss b/src/components/Paginator/Paginator.scss index 03e27066..dd46a713 100644 --- a/src/components/Paginator/Paginator.scss +++ b/src/components/Paginator/Paginator.scss @@ -9,6 +9,10 @@ display: flex; align-items: center; + [dir='rtl'] & { + flex-direction: row-reverse; + } + &__item { $item: &; diff --git a/src/components/SearchPage/SearchPage.scss b/src/components/SearchPage/SearchPage.scss index 57a0b559..a1c6c115 100644 --- a/src/components/SearchPage/SearchPage.scss +++ b/src/components/SearchPage/SearchPage.scss @@ -14,6 +14,10 @@ &__search-field-wrapper { display: flex; align-items: center; + + [dir='rtl'] & { + flex-direction: row-reverse; + } } &__search-button { diff --git a/src/components/Toc/Toc.scss b/src/components/Toc/Toc.scss index e83b4b8d..1c30226b 100644 --- a/src/components/Toc/Toc.scss +++ b/src/components/Toc/Toc.scss @@ -43,6 +43,10 @@ $leftOffset: 57px; display: flex; margin-right: 5px; flex-shrink: 0; + + [dir='rtl'] & { + margin-left: 5px; + } } &-header { @@ -114,6 +118,10 @@ $leftOffset: 57px; // recurcive padding > #{$class}__list { padding-left: 20px; + + [dir='rtl'] & { + padding-right: 20px; + } } } } diff --git a/src/components/TocItem/TocItem.scss b/src/components/TocItem/TocItem.scss index 70942fea..4e44d996 100644 --- a/src/components/TocItem/TocItem.scss +++ b/src/components/TocItem/TocItem.scss @@ -36,6 +36,10 @@ color: var(--g-color-text-primary); + [dir='rtl'] & { + padding: 7px 20px 7px 12px; + } + &_active { border-radius: 3px; background: var(--g-color-base-selection); @@ -61,5 +65,9 @@ &__icon { position: absolute; left: 0; + + [dir='rtl'] & { + right: 0; + } } } diff --git a/src/components/TocNavPanel/TocNavPanel.scss b/src/components/TocNavPanel/TocNavPanel.scss index de4236a1..c87a89a1 100644 --- a/src/components/TocNavPanel/TocNavPanel.scss +++ b/src/components/TocNavPanel/TocNavPanel.scss @@ -51,10 +51,20 @@ &_left svg { margin-right: 6px; + + [dir='rtl'] & { + margin-left: 6px; + transform: rotate(180deg); + } } &_right svg { margin-left: 6px; + + [dir='rtl'] & { + margin-right: 6px; + transform: rotate(180deg); + } } } diff --git a/src/components/ToggleArrow/ToggleArrow.scss b/src/components/ToggleArrow/ToggleArrow.scss index 669daf5b..eec8d472 100644 --- a/src/components/ToggleArrow/ToggleArrow.scss +++ b/src/components/ToggleArrow/ToggleArrow.scss @@ -11,6 +11,16 @@ &_vertical { transform: rotate(90deg); } + + [dir='rtl'] & { + &_horizontal { + transform: rotate(180deg); + } + + &_vertical { + transform: rotate(90deg); + } + } } &_open { diff --git a/src/models/index.ts b/src/models/index.ts index fe2315e2..6238747b 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -124,6 +124,7 @@ export interface Router { export enum Lang { Ru = 'ru', En = 'en', + He = 'he', } export interface Contributor {