From feb0a9c70e46e7667eacf22516bd5b93054a3f3d Mon Sep 17 00:00:00 2001 From: Talha12Shiekh Date: Tue, 28 Jul 2026 23:15:02 +0500 Subject: [PATCH] refactor(web): consolidate 12 near-identical SVG icon components into single pattern --- .../web/src/components/shared/AutofillSvg.js | 35 +- .../web/src/components/shared/CancelSvg.js | 23 +- .../web/src/components/shared/DownloadSvg.js | 13 +- packages/web/src/components/shared/Icons.js | 558 ++++++++++++++++++ .../web/src/components/shared/ListenSvg.js | 522 +--------------- packages/web/src/components/shared/MicSvg.js | 44 +- packages/web/src/components/shared/MuteSvg.js | 63 +- .../web/src/components/shared/SearchSvg.js | 31 +- .../src/components/shared/ThumbsDownSvg.js | 26 +- .../web/src/components/shared/ThumbsUpSvg.js | 26 +- 10 files changed, 567 insertions(+), 774 deletions(-) diff --git a/packages/web/src/components/shared/AutofillSvg.js b/packages/web/src/components/shared/AutofillSvg.js index f95cf74305..964292ec6e 100644 --- a/packages/web/src/components/shared/AutofillSvg.js +++ b/packages/web/src/components/shared/AutofillSvg.js @@ -1,36 +1,3 @@ -import React from 'react'; -import styled from '@emotion/styled'; - -const AutofillSvgIcon = styled.button` - display: flex; - margin-left: auto; - position: relative; - right: -3px; - border: none; - outline: none; - background: transparent; - padding: 0; - z-index: 111; - - svg { - cursor: pointer; - fill: #707070; - height: 17px; - } - - &:hover { - svg { - fill: #1c1a1a; - } - } -`; - -const SelectArrowSvg = props => ( - - - - - -); +import { SelectArrowSvg } from './Icons'; export default SelectArrowSvg; diff --git a/packages/web/src/components/shared/CancelSvg.js b/packages/web/src/components/shared/CancelSvg.js index 372b7855d4..4a645e51e7 100644 --- a/packages/web/src/components/shared/CancelSvg.js +++ b/packages/web/src/components/shared/CancelSvg.js @@ -1,24 +1,3 @@ -import React from 'react'; -import types from '@appbaseio/reactivecore/lib/utils/types'; - -const CancelSvg = ({ onClick }) => ( - - Clear - - - -); - -CancelSvg.propTypes = { - onClick: types.func, -}; +import { CancelSvg } from './Icons'; export default CancelSvg; diff --git a/packages/web/src/components/shared/DownloadSvg.js b/packages/web/src/components/shared/DownloadSvg.js index f55ffd6d00..edb1fa6c99 100644 --- a/packages/web/src/components/shared/DownloadSvg.js +++ b/packages/web/src/components/shared/DownloadSvg.js @@ -1,14 +1,3 @@ -import React from 'react'; -import styled from '@emotion/styled'; - -const DownloadSvgWrapper = styled.span` - text-decoration: underline; - text-decoration-thickness: 2px; - position: relative; - top: -1px; - margin-left: 2px; -`; - -const DownloadSvg = props => ; +import { DownloadSvg } from './Icons'; export default DownloadSvg; diff --git a/packages/web/src/components/shared/Icons.js b/packages/web/src/components/shared/Icons.js index 20a324536d..4621dc0ae2 100644 --- a/packages/web/src/components/shared/Icons.js +++ b/packages/web/src/components/shared/Icons.js @@ -1,6 +1,8 @@ import styled from '@emotion/styled'; import { object, string } from 'prop-types'; import React from 'react'; +import { Global, css } from '@emotion/core'; +import types from '@appbaseio/reactivecore/lib/utils/types'; const ThemedSVG = styled.svg` color: ${props => props.theme.colors.primaryColor}; @@ -59,3 +61,559 @@ export const CameraIcon = ({ size = '30px', ...props }) => ( CameraIcon.propTypes = { size: string, }; + +const iconRegistry = { + cancel: { + viewBox: '0 0 24 24', + children: ( + + Clear + + + + ), + defaultProps: { + alt: 'Clear', + className: 'cancel-icon', + height: '20px', + width: '20px', + }, + }, + search: { + viewBox: '0 0 15 15', + children: ( + + Search + + + ), + defaultProps: { + alt: 'Search', + className: 'search-icon', + height: '12', + style: { + transform: 'scale(1.35)', + position: 'relative', + }, + }, + }, + thumbsUp: { + viewBox: '0 0 24 24', + children: ( + + ), + defaultProps: { + stroke: 'currentColor', + fill: 'none', + strokeWidth: '2', + strokeLinecap: 'round', + strokeLinejoin: 'round', + height: '1em', + width: '1em', + }, + }, + thumbsDown: { + viewBox: '0 0 24 24', + children: ( + + ), + defaultProps: { + stroke: 'currentColor', + fill: 'none', + strokeWidth: '2', + strokeLinecap: 'round', + strokeLinejoin: 'round', + height: '1em', + width: '1em', + }, + }, + mic: { + viewBox: '0 0 480 480', + children: ( + + + + + + + + + + ), + defaultProps: { + id: 'el_xS0FRzQjJ', + width: 28, + height: 28, + style: { transform: 'scale(1.5)' }, + }, + }, + mute: { + viewBox: '0 0 480 480', + children: ( + + + + + + + + + + + ), + defaultProps: { + id: 'el_D1rEpH2zj', + width: 28, + height: 28, + style: { transform: 'scale(1.5)' }, + }, + }, + listen: { + viewBox: '0 0 480 480', + children: ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ), + defaultProps: { + xmlnsXlink: 'http://www.w3.org/1999/xlink', + id: 'el_hiibMG0x-', + width: 28, + height: 29, + style: { transform: 'scale(1.5)' }, + }, +}, +}; + +export const Icon = React.forwardRef(({ name, style, ...props }, ref) => { + const iconConfig = iconRegistry[name]; + if (!iconConfig) return null; + + const { children, viewBox, defaultProps } = iconConfig; + + return ( + + {children} + + ); +}); + +Icon.propTypes = { + name: string.isRequired, + style: object, +}; + +export const CancelSvg = React.forwardRef((props, ref) => ); +export const SearchSvg = React.forwardRef((props, ref) => ); +export const ThumbsUpSvg = React.forwardRef((props, ref) => ); +export const ThumbsDownSvg = React.forwardRef((props, ref) => ); +export const MicSvg = React.forwardRef((props, ref) => ); +export const MuteSvg = React.forwardRef((props, ref) => ); +export const ListenSvg = React.forwardRef((props, ref) => ); + +CancelSvg.propTypes = { + onClick: types.func, +}; + +SearchSvg.propTypes = { + style: types.style, +}; + +ThumbsUpSvg.propTypes = { + onClick: types.func, + className: types.string, +}; + +ThumbsDownSvg.propTypes = { + onClick: types.func, + className: types.string, +}; + +const AutofillSvgIcon = styled.button` + display: flex; + margin-left: auto; + position: relative; + right: -3px; + border: none; + outline: none; + background: transparent; + padding: 0; + z-index: 111; + + svg { + cursor: pointer; + fill: #707070; + height: 17px; + } + + &:hover { + svg { + fill: #1c1a1a; + } + } +`; + +export const SelectArrowSvg = props => ( + + + + + +); + +const DownloadSvgWrapper = styled.span` + text-decoration: underline; + text-decoration-thickness: 2px; + position: relative; + top: -1px; + margin-left: 2px; +`; + +export const DownloadSvg = props => ; diff --git a/packages/web/src/components/shared/ListenSvg.js b/packages/web/src/components/shared/ListenSvg.js index 5b94a18519..337a92d4c4 100644 --- a/packages/web/src/components/shared/ListenSvg.js +++ b/packages/web/src/components/shared/ListenSvg.js @@ -1,523 +1,3 @@ -import React from 'react'; -import { Global, css } from '@emotion/core'; - -const ListenSvg = props => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -); +import { ListenSvg } from './Icons'; export default ListenSvg; diff --git a/packages/web/src/components/shared/MicSvg.js b/packages/web/src/components/shared/MicSvg.js index 87afd55078..e72ea8fde2 100644 --- a/packages/web/src/components/shared/MicSvg.js +++ b/packages/web/src/components/shared/MicSvg.js @@ -1,45 +1,3 @@ -import React from 'react'; -import { Global, css } from '@emotion/core'; - -const MicSvg = props => ( - - - - - - - - - - - -); +import { MicSvg } from './Icons'; export default MicSvg; diff --git a/packages/web/src/components/shared/MuteSvg.js b/packages/web/src/components/shared/MuteSvg.js index cc3a236c72..300a5ec65a 100644 --- a/packages/web/src/components/shared/MuteSvg.js +++ b/packages/web/src/components/shared/MuteSvg.js @@ -1,64 +1,3 @@ -import React from 'react'; -import { Global, css } from '@emotion/core'; - -const MuteSvg = props => ( - - - - - - - - - - - - -); +import { MuteSvg } from './Icons'; export default MuteSvg; diff --git a/packages/web/src/components/shared/SearchSvg.js b/packages/web/src/components/shared/SearchSvg.js index de11da159b..6a4952a65a 100644 --- a/packages/web/src/components/shared/SearchSvg.js +++ b/packages/web/src/components/shared/SearchSvg.js @@ -1,32 +1,3 @@ -import types from '@appbaseio/reactivecore/lib/utils/types'; -import React from 'react'; - -const SearchSvg = (props = {}) => ( - - Search - - -); -SearchSvg.propTypes = { - style: types.style, -}; +import { SearchSvg } from './Icons'; export default SearchSvg; diff --git a/packages/web/src/components/shared/ThumbsDownSvg.js b/packages/web/src/components/shared/ThumbsDownSvg.js index deb3671da5..bf3a06fbf0 100644 --- a/packages/web/src/components/shared/ThumbsDownSvg.js +++ b/packages/web/src/components/shared/ThumbsDownSvg.js @@ -1,27 +1,3 @@ -import React from 'react'; -import types from '@appbaseio/reactivecore/lib/utils/types'; - -const ThumbsDownSvg = ({ onClick, className = '' }) => ( - - - -); - -ThumbsDownSvg.propTypes = { - onClick: types.func, - className: types.string, -}; +import { ThumbsDownSvg } from './Icons'; export default ThumbsDownSvg; diff --git a/packages/web/src/components/shared/ThumbsUpSvg.js b/packages/web/src/components/shared/ThumbsUpSvg.js index 937fbfbf1d..024ca5f59e 100644 --- a/packages/web/src/components/shared/ThumbsUpSvg.js +++ b/packages/web/src/components/shared/ThumbsUpSvg.js @@ -1,27 +1,3 @@ -import React from 'react'; -import types from '@appbaseio/reactivecore/lib/utils/types'; - -const ThumbsUpSvg = ({ onClick, className = '' }) => ( - - - -); - -ThumbsUpSvg.propTypes = { - onClick: types.func, - className: types.string, -}; +import { ThumbsUpSvg } from './Icons'; export default ThumbsUpSvg;