Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions src/components/default-error-fallback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,16 @@ const RightPanel = () => {
};

export default function DefaultErrorFallback() {
const { isRTL } = useI18n();
const isRtl = isRTL();

const href = isRtl
? './main_window/styles/wordpress-components-style-rtl.css'
: './main_window/styles/wordpress-components-style.css';

return (
<div dir={ 'ltr' }>
<DynamicStylesheet
id="wordpress-components-style"
href={ '../main_window/styles/wordpress-components-style.css' }
/>
<div dir={ isRtl ? 'rtl' : 'ltr' }>
<DynamicStylesheet id="wordpress-components-style-error-fallback" href={ href } />
<VStack
className={ cx(
'h-screen bg-chrome backdrop-blur-3xl pr-chrome app-drag-region',
Expand Down
9 changes: 8 additions & 1 deletion src/components/dynamic-stylesheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,14 @@ export const DynamicStylesheet = ( { id, href }: DynamicStylesheetProps ) => {
linkElement.id = id;
linkElement.rel = 'stylesheet';
linkElement.type = 'text/css';
document.head.appendChild( linkElement );
const firstStylesheet =
document.head.querySelector( 'link[rel="stylesheet"]' ) ||
document.head.querySelector( 'style' );
if ( firstStylesheet ) {
document.head.insertBefore( linkElement, firstStylesheet );
} else {
document.head.appendChild( linkElement );
}
wasCreatedByUsRef = true;
}
linkElementRef.current = linkElement;
Expand Down
2 changes: 2 additions & 0 deletions src/components/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import App from 'src/components/app';
import AuthProvider from 'src/components/auth-provider';
import CrashTester from 'src/components/crash-tester';
import ErrorBoundary from 'src/components/error-boundary';
import { WordPressStyles } from 'src/components/wordpress-styles';
import { SyncSitesProvider } from 'src/hooks/sync-sites/sync-sites-context';
import { ContentTabsProvider } from 'src/hooks/use-content-tabs';
import { FeatureFlagsProvider } from 'src/hooks/use-feature-flags';
Expand All @@ -34,6 +35,7 @@ const Root = () => {
<CacheProvider value={ emotionCache }>
<ReduxProvider store={ store }>
<I18nProvider i18n={ defaultI18n }>
<WordPressStyles />
<AuthProvider>
<ContentTabsProvider>
<SiteDetailsProvider>
Expand Down
6 changes: 3 additions & 3 deletions src/components/tests/dynamic-stylesheet.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,18 @@ describe( 'DynamicStylesheet', () => {
);
render( <DynamicStylesheet id="second-style" href="/second.css" /> );

// Get initial order
// Get initial order (new elements are inserted before existing ones)
const allLinks = document.head.querySelectorAll( 'link[id]' );
const initialOrder = Array.from( allLinks ).map( ( link ) => link.id );
expect( initialOrder ).toEqual( [ 'first-style', 'second-style' ] );
expect( initialOrder ).toEqual( [ 'second-style', 'first-style' ] );

// Update href of the first element
rerender1( <DynamicStylesheet id="first-style" href="/first-updated.css" /> );

// Order should be preserved
const allLinksAfterUpdate = document.head.querySelectorAll( 'link[id]' );
const orderAfterUpdate = Array.from( allLinksAfterUpdate ).map( ( link ) => link.id );
expect( orderAfterUpdate ).toEqual( [ 'first-style', 'second-style' ] );
expect( orderAfterUpdate ).toEqual( [ 'second-style', 'first-style' ] );

// Verify the href was actually updated
const firstElement = document.getElementById( 'first-style' ) as HTMLLinkElement;
Expand Down
25 changes: 25 additions & 0 deletions src/components/wordpress-styles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useI18n } from '@wordpress/react-i18n';
import { DynamicStylesheet } from 'src/components/dynamic-stylesheet';

const WORDPRESS_STYLES_ID = 'wordpress-components-style';

// @ts-expect-error - import.meta syntax is not supported by TypeScript's commonjs module setting,
// but Vite handles this at build time and replaces it with the actual value
const isDevelopment = import.meta.env.DEV;

const WORDPRESS_STYLES_LTR = isDevelopment
? '/node_modules/@wordpress/components/build-style/style.css'
: './main_window/styles/wordpress-components-style.css';

const WORDPRESS_STYLES_RTL = isDevelopment
? '/node_modules/@wordpress/components/build-style/style-rtl.css'
: './main_window/styles/wordpress-components-style-rtl.css';

export const WordPressStyles = () => {
const { isRTL } = useI18n();
const isRtl = isRTL();

const href = isRtl ? WORDPRESS_STYLES_RTL : WORDPRESS_STYLES_LTR;

return <DynamicStylesheet id={ WORDPRESS_STYLES_ID } href={ href } />;
};
4 changes: 1 addition & 3 deletions src/index.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
/* Import WordPress component styles - these are handled by Vite */
@import '@wordpress/components/build-style/style.css';

/* WordPress component styles are loaded dynamically via WordPressStyles component */
@tailwind base;
@tailwind components;
@tailwind utilities;
Expand Down