@@ -57,7 +57,7 @@ npm install remix-development-tools -D
5757
5858``` diff
5959// We'll lazy load RemixDevTools to ensure it doesn't contribute to production bundle size
60- + import { lazy } from "react";
60+ + import { lazy, Suspense } from "react";
6161+ import rdtStylesheet from "remix-development-tools/stylesheet.css";
6262+ const RemixDevTools =
6363+ process.env.NODE_ENV === "development"
@@ -85,7 +85,7 @@ export default function App() {
8585 <ScrollRestoration />
8686 <Scripts />
8787 <LiveReload />
88- + {RemixDevTools && <RemixDevTools />}
88+ + {RemixDevTools && <Suspense>< RemixDevTools /></Suspense >}
8989 </body>
9090 </html>
9191 );
@@ -101,15 +101,230 @@ The `RemixDevTools` component accepts the following props:
101101- ` position ` : The position of the Remix Development Tools trigger. Defaults to ` bottom-right ` .
102102- ` requireUrlFlag ` : Requires rdt=true to be present in the URL search to open the Remix Development Tools. Defaults to ` false ` .
103103- ` showRouteBoundaries ` : Allows you to see each Outlet and route boundaries by coloring the background. Defaults to ` false ` .
104+ - ` hideUntilHover ` : Allows you to hide the trigger until you hover over it. Defaults to ` false ` .
105+ - ` additionalTabs ` : Allows you to provide additional tabs to the Remix Development Tools. Defaults to ` [] ` .
106+
107+ ## Plugins
108+
109+ Writing plugins for Remix Development Tools is easy. You can write a plugin that adds a new tab to the Remix Development Tools in the following way:
110+ 1 . Create a new file in your project called ` remix-dev-tools-plugin.tsx `
111+ 2 . Implement your jsx component and add the logic you wish to add to the Remix Development Tools.
112+ 3 . Export a function with the following contract:
113+
114+ ``` jsx
115+
116+ const MyComponent = () => {
117+ // Implement your logic here
118+ return < div> My Component< / div>
119+ }
120+
121+ export function remixDevToolsPlugin (yourOptions ?: { ... }): JSX.Element {
122+ return {
123+ // can't be page, terminal or routes, must be unique
124+ id: " my-plugin" ,
125+ // Name that is shown in the tab next to the icon
126+ name: " My Plugin" ,
127+ // Icon to be shown in the tab
128+ icon: < MyIcon size= {16 } / > ,
129+ // The component to be rendered when the tab is active
130+ component: < MyComponent / > ,
131+ // Whether the tab requires the Remix Forge VS Code extension to be connected to be shown
132+ requiresForge: false ,
133+ }
134+ }
135+ ```
136+ 4 . Import it in your ` root.tsx ` file and pass it to your Remix Development Tools:
137+ ``` diff
138+ import { remixDevToolsPlugin } from "./remix-dev-tools-plugin";
139+
140+ - <RemixDevTools />
141+ + <RemixDevTools additionalTabs={[remixDevToolsPlugin()]} />
142+
143+ ```
144+ 5 . You should now see your plugin in the Remix Development Tools as a new tab.
145+
146+
147+ ### Using Remix Forge with your plugin
148+
149+ If you want to use Remix Forge with your plugin you can do so by setting the ` requiresForge ` property to ` true ` in your plugin. This will make sure that the plugin is only shown when the Remix Forge VS Code extension is connected.
150+
151+ 1 . Follow the above guide to create a plugin.
152+ 2 . Import the following hook from remix-development-tools:
153+
154+ ``` jsx
155+ import { useRemixForgeSocket } from " remix-development-tools" ;
156+ ```
157+
158+ 3 . Use the hook in your plugin to get the Remix Forge socket:
159+ ``` jsx
160+ const MyComponent = () => {
161+ const socket = useRemixForgeSocket ();
162+ // Implement your logic here
163+ return < div> My Component< / div>
164+ }
165+ ```
166+ 4 . You can now use the socket to send messages to the Remix Forge VS Code extension. For now it accepts reading/deleting/opening files in VS Code
167+
168+ ``` jsx
169+ const MyComponent = () => {
170+ const socket = useRemixForgeSocket ();
171+ const runCommand = () => {
172+ socket .sendJsonMessage ({ subtype: " read_file" , path: " package.json" })
173+ }
174+ // Implement your logic here
175+ return < div onClick= {runCommand}> My Component< / div>
176+ }
177+ ```
178+
179+ 5 . The following contract is returned from the extension:
180+
181+ ``` ts
182+ interface RemixForgeResponse {
183+ type: " plugin" ;
184+ subtype: " read_file" | " open_file" | " delete_file" | " write_file" ;
185+ error: boolean ;
186+ data: string | null ;
187+ }
188+ ```
189+ 6 . Make sure you check if the type and subtype match your needs before using the data.
190+ 7 . Refer to ` react-use-websocket ` for more information on how to use the socket and what options it accepts because that is what is used under the hood.
191+ 8 . After you're done share your plugin with the community by opening a discussion!
192+
193+ ## Troubleshooting
194+
195+ If you are having trouble getting Remix Development Tools to work, please try the following:
196+
197+ ### RemixDevTools are not appearing in the DOM / causing re-renders
198+
199+ 1 . Move the RemixDevTools as high as possible in your root.tsx file. It should be the first thing in the body tag.
200+
201+ ``` diff
202+ export default function App() {
203+ return (
204+ <html lang="en">
205+ <head>
206+ <meta charSet="utf-8" />
207+ <meta name="viewport" content="width=device-width,initial-scale=1" />
208+ <Meta />
209+ <Links />
210+ </head>
211+ <body>
212+ <Outlet />
213+ <ScrollRestoration />
214+ <Scripts />
215+ <LiveReload />
216+ + {RemixDevTools && <Suspense><RemixDevTools /></Suspense>}
217+ </body>
218+ </html>
219+ );
220+ }
221+ ```
222+
223+ 2 . Make sure the RemixDevTools are not wrapped in custom providers that might cause re-renders.
224+
225+ ``` jsx
226+ const ThemeProvider = () => {
227+ return (
228+ < ThemeContext .Provider value= {theme}>
229+ < RemixDevTools / >
230+ < / ThemeContext .Provider >
231+ );
232+ }
233+
234+ export default function App () {
235+ return (
236+ < html lang= " en" >
237+ < head>
238+ < meta charSet= " utf-8" / >
239+ < meta name= " viewport" content= " width=device-width,initial-scale=1" / >
240+ < Meta / >
241+ < Links / >
242+ < / head>
243+ < body>
244+ < ThemeProvider >
245+ < Outlet / >
246+ < / ThemeProvider>
247+ < ScrollRestoration / >
248+ < Scripts / >
249+ < LiveReload / >
250+ < / body>
251+ < / html>
252+ );
253+ }
254+
255+ ```
256+
257+ instead do this:
258+
259+ ``` diff
260+ const ThemeProvider = () => {
261+ return (
262+ <ThemeContext.Provider value={theme}>
263+ - <RemixDevTools />
264+ + <Outlet />
265+ </ThemeContext.Provider>
266+ );
267+ }
268+
269+ export default function App() {
270+ return (
271+ <html lang="en">
272+ <head>
273+ <meta charSet="utf-8" />
274+ <meta name="viewport" content="width=device-width,initial-scale=1" />
275+ <Meta />
276+ <Links />
277+ </head>
278+ <body>
279+ - <ThemeProvider >
280+ - <Outlet />
281+ - </ThemeProvider>
282+ + <ThemeProvider />
283+ <ScrollRestoration />
284+ <Scripts />
285+ <LiveReload />
286+ + <RemixDevTools />
287+ </body>
288+ </html>
289+ );
290+ }
291+
292+ ```
293+
294+ ### HMR is failing with RDT
295+
296+ Wrap the ` RemixDevTools ` component in a ` Suspense ` component.
297+
298+ ``` diff
299+ export default function App() {
300+ return (
301+ <html lang="en">
302+ <head>
303+ <meta charSet="utf-8" />
304+ <meta name="viewport" content="width=device-width,initial-scale=1" />
305+ <Meta />
306+ <Links />
307+ </head>
308+ <body>
309+ <Outlet />
310+ <ScrollRestoration />
311+ <Scripts />
312+ <LiveReload />
313+ + {RemixDevTools && <Suspense><RemixDevTools /></Suspense>}
314+ </body>
315+ </html>
316+ );
317+ }
318+ ```
104319
105320## Contributing
106321
107322Contributions to Remix Development Tools are welcome! To contribute, please follow these guidelines:
108323
1093241 . Fork the repository and clone it locally.
110- 2 . Create a new branch for your feature or bug fix.
111- 3 . Run ` npm run setup ` to get your development environment set up.
325+ 2 . Create a new branch for your feature or bug fix.
1123264 . Run ` npm run dev ` to start the development server.
327+ 4 . Run ` npm run epic-dev ` to start the development server with the epic stack.
1133285 . Implement your changes, adhering to the existing code style and best practices.
1143295 . Please add tests for any new features or bug fixes.
1153306 . Commit and push your changes to your forked repository.
0 commit comments