From e14795cd275061640c57babe0ec38ba66003c050 Mon Sep 17 00:00:00 2001 From: symonbaikov Date: Thu, 5 Jun 2025 18:35:55 +0300 Subject: [PATCH] feat: use react-world-flags for language selector and unify flag styles - Switched language selector flags to react-world-flags for reliable SVG rendering - Added dedicated SCSS module for flag styling to ensure consistent size and alignment - All flags are now perfectly centered and visually unified in the dropdown - Removed old flag-icons integration and related styles --- client/package-lock.json | 40 +++++++++++++++++-- client/package.json | 1 + .../AccountPane/AccountPane.jsx | 18 ++++++++- .../UserSettingsModal/LocaleFlag.module.scss | 12 ++++++ 4 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 client/src/components/users/UserSettingsModal/LocaleFlag.module.scss diff --git a/client/package-lock.json b/client/package-lock.json index 2295ac8d..c1330ab3 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -75,6 +75,7 @@ "react-router-dom": "^6.30.1", "react-textarea-autosize": "^8.5.9", "react-time-ago": "^7.3.3", + "react-world-flags": "^1.6.0", "redux": "^4.2.1", "redux-logger": "^3.0.6", "redux-orm": "^0.16.2", @@ -4734,11 +4735,19 @@ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, + "node_modules/@types/prop-types": { + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "license": "MIT" + }, "node_modules/@types/react": { - "version": "19.1.6", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.6.tgz", - "integrity": "sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q==", + "version": "18.3.23", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz", + "integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==", + "license": "MIT", "dependencies": { + "@types/prop-types": "*", "csstype": "^3.0.2" } }, @@ -12531,6 +12540,20 @@ "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/react-world-flags": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/react-world-flags/-/react-world-flags-1.6.0.tgz", + "integrity": "sha512-eutSeAy5YKoVh14js/JUCSlA6EBk1n4k+bDaV+NkNB50VhnG+f4QDTpYycnTUTsZ5cqw/saPmk0Z4Fa0VVZ1Iw==", + "license": "MIT", + "dependencies": { + "svg-country-flags": "^1.2.10", + "svgo": "^3.0.2", + "world-countries": "^5.0.0" + }, + "peerDependencies": { + "react": ">=0.14" + } + }, "node_modules/read-package-up": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz", @@ -14169,6 +14192,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-country-flags": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/svg-country-flags/-/svg-country-flags-1.2.10.tgz", + "integrity": "sha512-xrqwo0TYf/h2cfPvGpjdSuSguUbri4vNNizBnwzoZnX0xGo3O5nGJMlbYEp7NOYcnPGBm6LE2axqDWSB847bLw==", + "license": "PD" + }, "node_modules/svg-parser": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", @@ -15228,6 +15257,11 @@ "node": ">=0.10.0" } }, + "node_modules/world-countries": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/world-countries/-/world-countries-5.1.0.tgz", + "integrity": "sha512-CXR6EBvTbArDlDDIWU3gfKb7Qk0ck2WNZ234b/A0vuecPzIfzzxH+O6Ejnvg1sT8XuiZjVlzOH0h08ZtaO7g0w==" + }, "node_modules/wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", diff --git a/client/package.json b/client/package.json index f52e3428..1f290744 100755 --- a/client/package.json +++ b/client/package.json @@ -146,6 +146,7 @@ "react-router-dom": "^6.30.1", "react-textarea-autosize": "^8.5.9", "react-time-ago": "^7.3.3", + "react-world-flags": "^1.6.0", "redux": "^4.2.1", "redux-logger": "^3.0.6", "redux-orm": "^0.16.2", diff --git a/client/src/components/users/UserSettingsModal/AccountPane/AccountPane.jsx b/client/src/components/users/UserSettingsModal/AccountPane/AccountPane.jsx index 2997a218..5636423b 100644 --- a/client/src/components/users/UserSettingsModal/AccountPane/AccountPane.jsx +++ b/client/src/components/users/UserSettingsModal/AccountPane/AccountPane.jsx @@ -7,6 +7,7 @@ import React, { useCallback } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; import { Button, Divider, Dropdown, Header, Tab } from 'semantic-ui-react'; +import Flag from 'react-world-flags'; import { usePopupInClosableContext } from '../../../../hooks'; import locales from '../../../../locales'; @@ -21,6 +22,7 @@ import selectors from '../../../../selectors'; import entryActions from '../../../../entry-actions'; import styles from './AccountPane.module.scss'; +import localeFlagStyles from '../LocaleFlag.module.scss'; const AccountPane = React.memo(() => { const user = useSelector(selectors.selectCurrentUser); @@ -70,8 +72,20 @@ const AccountPane = React.memo(() => { }, ...locales.map((locale) => ({ value: locale.language, - flag: locale.country, - text: locale.name, + text: ( + <> + {locale.country && ( + + } + /> + + )} + {locale.name} + + ), })), ]} value={user.language || 'auto'} diff --git a/client/src/components/users/UserSettingsModal/LocaleFlag.module.scss b/client/src/components/users/UserSettingsModal/LocaleFlag.module.scss new file mode 100644 index 00000000..51584a30 --- /dev/null +++ b/client/src/components/users/UserSettingsModal/LocaleFlag.module.scss @@ -0,0 +1,12 @@ +.localeFlag { + width: 24px; + height: 16px; + margin-right: 8px; + border-radius: 2px; + object-fit: cover; + display: inline-flex; + align-items: center; + justify-content: center; + vertical-align: middle; + background: #f5f5f5; // fallback bg для прозрачных флагов +}