@@ -10,6 +10,7 @@ import {
1010 DEFAULT_MAX_RETRIES ,
1111} from '@/constants/zendesk-timing' ;
1212import { setupZendeskObserver } from '@/utils/zendesk-observer' ;
13+ import { ZENDESK_SEND_BUTTON_SELECTOR } from '@/constants/zendesk-selectors' ;
1314
1415interface UseZendeskIframeStylesOptions {
1516 zendeskReady : boolean ;
@@ -47,7 +48,12 @@ export function useZendeskIframeStyles({
4748 ( ( retries ?: number , delay ?: number ) => void ) | null
4849 > ( null ) ;
4950 const observerRef = useRef < MutationObserver | null > ( null ) ;
51+ const buttonObserverRef = useRef < MutationObserver | null > ( null ) ;
5052 const isMountedRef = useRef ( true ) ;
53+ // Track buttons that have already had their SVG replaced to avoid duplicates
54+ const replacedButtonsRef = useRef < WeakSet < HTMLElement > > (
55+ new WeakSet < HTMLElement > ( ) ,
56+ ) ;
5157
5258 // Injects styles into the Zendesk iframe document. Retries if iframe is not
5359 // available yet.
@@ -114,6 +120,45 @@ export function useZendeskIframeStyles({
114120 [ styles ] ,
115121 ) ;
116122
123+ // Replaces the SVG in the send button with a custom icon
124+ const replaceSendButtonSvg = useCallback ( ( iframeDoc : Document ) : void => {
125+ try {
126+ // Find the send button using the proper selector
127+ const sendButton = iframeDoc . querySelector < HTMLElement > (
128+ ZENDESK_SEND_BUTTON_SELECTOR ,
129+ ) ;
130+
131+ if ( ! sendButton ) {
132+ return ;
133+ }
134+
135+ // Skip if we've already replaced this button's SVG
136+ if ( replacedButtonsRef . current . has ( sendButton ) ) {
137+ return ;
138+ }
139+
140+ const svg = sendButton . querySelector ( 'svg' ) ;
141+
142+ if ( svg ) {
143+ sendButton . dataset . customized = 'true' ;
144+
145+ // Replace with external SVG file
146+ svg . outerHTML = `
147+ <img src="static-assets/images/Send-Plane-Solid-16.svg"
148+ width="20"
149+ height="20"
150+ alt="Send"
151+ style="display: block;" />
152+ ` ;
153+
154+ // Mark this button as replaced
155+ replacedButtonsRef . current . add ( sendButton ) ;
156+ }
157+ } catch ( error ) {
158+ window . fireJse ?.( error ) ;
159+ }
160+ } , [ ] ) ;
161+
117162 // Store `injectStyles` in a ref to enable recursive calls. ESLint flags
118163 // self-referential calls within useCallback
119164 useEffect ( ( ) => {
@@ -142,13 +187,15 @@ export function useZendeskIframeStyles({
142187
143188 // Set up MutationObserver to re-inject styles if iframe reloads
144189 let observerCleanup : ( ( ) => void ) | null = null ;
190+ let buttonObserverCleanup : ( ( ) => void ) | null = null ;
145191
146192 // Set up observer after a delay to ensure iframe is ready
147193 observerTimeout = setTimeout ( ( ) => {
148194 if ( ! isMountedRef . current ) {
149195 return ;
150196 }
151197
198+ // Observer for style injection (watches head)
152199 observerCleanup = setupZendeskObserver ( {
153200 onMutation : ( iframeDoc ) => {
154201 // Check if style element was removed (iframe reloaded)
@@ -165,6 +212,23 @@ export function useZendeskIframeStyles({
165212 isMountedRef,
166213 observerRef,
167214 } ) ;
215+
216+ // Observer for send button SVG replacement (watches body)
217+ // The send button appears dynamically when user clicks in textarea
218+ buttonObserverCleanup = setupZendeskObserver ( {
219+ onMutation : ( iframeDoc ) => {
220+ // Try to replace SVG whenever DOM mutations occur
221+ replaceSendButtonSvg ( iframeDoc ) ;
222+ } ,
223+ onSetup : ( iframeDoc ) => {
224+ // Try immediately in case button already exists
225+ replaceSendButtonSvg ( iframeDoc ) ;
226+ } ,
227+ target : 'body' ,
228+ retryOnNotReady : false ,
229+ isMountedRef,
230+ observerRef : buttonObserverRef ,
231+ } ) ;
168232 } , OBSERVER_SETUP_DELAY_MS ) ;
169233
170234 return ( ) => {
@@ -180,16 +244,26 @@ export function useZendeskIframeStyles({
180244 clearTimeout ( observerTimeout ) ;
181245 }
182246
183- // Clean up observer
247+ // Clean up observers
184248 if ( observerCleanup ) {
185249 observerCleanup ( ) ;
186250 }
187251
252+ if ( buttonObserverCleanup ) {
253+ buttonObserverCleanup ( ) ;
254+ }
255+
188256 if ( observerRef . current ) {
189257 observerRef . current . disconnect ( ) ;
190258
191259 observerRef . current = null ;
192260 }
261+
262+ if ( buttonObserverRef . current ) {
263+ buttonObserverRef . current . disconnect ( ) ;
264+
265+ buttonObserverRef . current = null ;
266+ }
193267 } ;
194- } , [ zendeskReady , styles , injectStyles ] ) ;
268+ } , [ zendeskReady , styles , injectStyles , replaceSendButtonSvg ] ) ;
195269}
0 commit comments