Skip to content

Commit e04bb11

Browse files
Feat seo serp preview (#373)
* refactor(devtools): remove SeoTab component and related functionality This commit deletes the SeoTab component from the devtools package, which included social media preview functionality and meta tag analysis. The removal streamlines the codebase by eliminating unused features. * refactor(devtools): rename SocialPreviewSection to SocialPreviewsSection This commit updates the naming of the SocialPreviewSection component to SocialPreviewsSection for consistency and clarity in the SEO tab of the devtools package. The change improves code readability and aligns with the pluralization of the component's purpose. * refactor(devtools): rename social-preview file to social-previews and update import path This commit renames the social-preview.tsx file to social-previews.tsx for consistency with the component naming convention. The import path in the SeoTab component is also updated accordingly, enhancing code clarity and maintainability. * feat(devtools): add SEO tab navigation and enhance SocialPreviewsSection This commit introduces a navigation bar in the SeoTab component, allowing users to switch between 'Social Previews' and 'SERP Preview' sections. It also updates the SocialPreviewsSection to conditionally render its title based on a new prop, improving flexibility in display options. New styles for the navigation elements are added to enhance the user interface. * feat(devtools): enhance SERP and Social Previews with new styles and data handling This commit introduces new styles for the SERP snippet and updates the SERP and Social Previews sections to dynamically display data from the current page's metadata. The SocialPreviewsSection and SerpPreviewSection components are refactored to improve clarity and functionality, removing unnecessary props and enhancing the user interface with better styling. * refactor(devtools): update SERP snippet styles and structure This commit refactors the SERP snippet styles by renaming the `serpSnippetUrlRow` to `serpSnippetTopRow` and introduces new styles for site name and URL. The structure of the SERP preview is enhanced to better organize the display of site information, improving the overall layout and visual consistency. * feat(devtools): enhance SERP preview with truncation logic and overflow reporting This commit adds functionality to the SERP preview section, implementing text truncation for the title and description based on specified width limits. It introduces new state management for overflow detection and displays warnings when the title or description exceeds the defined character limits. Additionally, new styles are added to support the hidden measurement elements for accurate text sizing. * feat(devtools): add SERP overflow reporting and improve styles This commit enhances the SERP preview section by introducing a new overflow reporting mechanism for the title and description. It adds a list of issues when the title or description exceeds specified limits, improving user feedback. Additionally, new styles are implemented for better visual presentation of error messages in the SERP preview. * feat(devtools): add meta description and default favicon styles This commit enhances the SEO capabilities of the basic example by adding a meta description tag for improved search engine visibility. Additionally, it introduces new styles for a default favicon, ensuring a consistent visual representation when no favicon is provided. This improves user feedback in the SERP preview section. * feat(devtools): enhance SERP preview layout with new styles This commit introduces new styles for the SERP preview section, including a dedicated block for the preview and a label for better organization. The layout improvements enhance the visual presentation of the desktop preview, ensuring a clearer display of the site name, URL, title, and description. * feat(devtools): enhance SERP preview for mobile with new styles and overflow reporting This commit introduces new styles for the mobile SERP preview, including a dedicated snippet layout and improved overflow reporting for the title and description. It adds functionality to handle mobile-specific text truncation and displays warnings for descriptions exceeding a three-line limit, enhancing user feedback and visual consistency across devices. * feat(devtools): implement comprehensive SERP issue reporting and enhance component structure This commit introduces a robust mechanism for reporting SERP issues, including checks for favicon, title, and description validity. It refactors the SERP preview component to utilize a more structured approach for handling overflow conditions and displaying relevant warnings. Additionally, it enhances the layout for both desktop and mobile previews, ensuring a consistent and informative user experience across devices. * refactor(devtools): update SERP preview truncation logic and improve character limits This commit refines the SERP preview component by replacing pixel-based truncation with character-based limits for titles and descriptions. It introduces constants for maximum character counts, enhancing the clarity of the truncation logic. Additionally, it simplifies the component structure by removing unnecessary measurement elements, improving overall readability and maintainability. * refactor(devtools): streamline SERP preview component and improve character limit handling This commit refines the SERP preview component by enhancing the character limit handling for titles and descriptions. It simplifies the component structure, removing redundant elements, and improves the overall readability and maintainability of the code. Additionally, it ensures consistent behavior across different display scenarios. * refactor(devtools): reorder imports in social-previews component for consistency --------- Co-authored-by: Alem Tuzlak <t.zlak97@gmail.com>
1 parent e89cff4 commit e04bb11

File tree

6 files changed

+522
-69
lines changed

6 files changed

+522
-69
lines changed

.changeset/vast-apes-attend.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tanstack/devtools': patch
3+
---
4+
5+
Implemented a new SERP (Search Engine Results Page) section in the SEO tab. This update introduces desktop and mobile preview of search results. It displays the current site's favicon, title and description while displaying errors and issues when they are not found or they exceed the character limit.

examples/react/basic/index.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@
2828
<meta name="twitter:url" content="https://example.com/basic" />
2929
<script src="https://unpkg.com/react-scan/dist/auto.global.js"></script>
3030
<title>Basic Example - TanStack Devtools</title>
31+
<meta
32+
name="description"
33+
content="A basic example of using TanStack Devtools with React."
34+
/>
35+
3136
<description
3237
>A basic example of using TanStack Devtools with React.</description
3338
>

packages/devtools/src/styles/use-styles.ts

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,32 @@ const stylesFactory = (theme: DevtoolsStore['settings']['theme']) => {
119119
margin-bottom: 2rem;
120120
border-radius: 0.75rem;
121121
`,
122+
seoSubNav: css`
123+
display: flex;
124+
flex-direction: row;
125+
gap: 0;
126+
margin-bottom: 1rem;
127+
border-bottom: 1px solid ${t(colors.gray[200], colors.gray[800])};
128+
`,
129+
seoSubNavLabel: css`
130+
padding: 0.5rem 1rem;
131+
font-size: 0.875rem;
132+
font-weight: 500;
133+
color: ${t(colors.gray[600], colors.gray[400])};
134+
background: none;
135+
border: none;
136+
border-bottom: 2px solid transparent;
137+
margin-bottom: -1px;
138+
cursor: pointer;
139+
font-family: inherit;
140+
&:hover {
141+
color: ${t(colors.gray[800], colors.gray[200])};
142+
}
143+
`,
144+
seoSubNavLabelActive: css`
145+
color: ${t(colors.gray[900], colors.gray[100])};
146+
border-bottom-color: ${t(colors.gray[900], colors.gray[100])};
147+
`,
122148
seoPreviewSection: css`
123149
display: flex;
124150
flex-direction: row;
@@ -205,6 +231,139 @@ const stylesFactory = (theme: DevtoolsStore['settings']['theme']) => {
205231
padding: 0 10px 8px 10px;
206232
font-size: 0.875rem;
207233
`,
234+
serpPreviewBlock: css`
235+
margin-bottom: 1.5rem;
236+
border: 1px solid ${t(colors.gray[200], colors.gray[700])};
237+
border-radius: 10px;
238+
padding: 1rem;
239+
`,
240+
serpPreviewLabel: css`
241+
font-size: 0.875rem;
242+
font-weight: 600;
243+
margin-bottom: 0.5rem;
244+
color: ${t(colors.gray[700], colors.gray[300])};
245+
`,
246+
serpSnippet: css`
247+
border: 1px solid ${t(colors.gray[100], colors.gray[800])};
248+
border-radius: 8px;
249+
padding: 1rem 1.25rem;
250+
background: ${t(colors.white, colors.darkGray[900])};
251+
max-width: 600px;
252+
font-family: ${fontFamily.sans};
253+
box-shadow: 0 1px 2px ${t('rgba(0,0,0,0.04)', 'rgba(0,0,0,0.08)')};
254+
`,
255+
serpSnippetMobile: css`
256+
border: 1px solid ${t(colors.gray[100], colors.gray[800])};
257+
border-radius: 8px;
258+
padding: 1rem 1.25rem;
259+
background: ${t(colors.white, colors.darkGray[900])};
260+
max-width: 380px;
261+
font-family: ${fontFamily.sans};
262+
box-shadow: 0 1px 2px ${t('rgba(0,0,0,0.04)', 'rgba(0,0,0,0.08)')};
263+
`,
264+
serpSnippetDescMobile: css`
265+
font-size: 0.875rem;
266+
color: ${t(colors.gray[700], colors.gray[300])};
267+
margin: 0;
268+
line-height: 1.5;
269+
display: -webkit-box;
270+
-webkit-box-orient: vertical;
271+
-webkit-line-clamp: 3;
272+
overflow: hidden;
273+
`,
274+
serpSnippetTopRow: css`
275+
display: flex;
276+
align-items: center;
277+
gap: 12px;
278+
margin-bottom: 8px;
279+
`,
280+
serpSnippetFavicon: css`
281+
width: 28px;
282+
height: 28px;
283+
border-radius: 50%;
284+
flex-shrink: 0;
285+
object-fit: contain;
286+
overflow: hidden;
287+
display: flex;
288+
align-items: center;
289+
justify-content: center;
290+
`,
291+
serpSnippetDefaultFavicon: css`
292+
width: 28px;
293+
height: 28px;
294+
background-color: ${t(colors.gray[200], colors.gray[800])};
295+
border-radius: 50%;
296+
flex-shrink: 0;
297+
object-fit: contain;
298+
overflow: hidden;
299+
display: flex;
300+
align-items: center;
301+
justify-content: center;
302+
`,
303+
serpSnippetSiteColumn: css`
304+
display: flex;
305+
flex-direction: column;
306+
gap: 0;
307+
min-width: 0;
308+
`,
309+
serpSnippetSiteName: css`
310+
font-size: 0.875rem;
311+
color: ${t(colors.gray[900], colors.gray[100])};
312+
line-height: 1.4;
313+
margin: 0;
314+
`,
315+
serpSnippetSiteUrl: css`
316+
font-size: 0.75rem;
317+
color: ${t(colors.gray[500], colors.gray[500])};
318+
line-height: 1.4;
319+
margin: 0;
320+
`,
321+
serpSnippetTitle: css`
322+
font-size: 1.25rem;
323+
font-weight: 400;
324+
color: ${t('#1a0dab', '#8ab4f8')};
325+
margin: 0 0 4px 0;
326+
line-height: 1.3;
327+
`,
328+
serpSnippetDesc: css`
329+
font-size: 0.875rem;
330+
color: ${t(colors.gray[700], colors.gray[300])};
331+
margin: 0;
332+
line-height: 1.5;
333+
`,
334+
serpMeasureHidden: css`
335+
position: absolute;
336+
left: -9999px;
337+
top: 0;
338+
visibility: hidden;
339+
pointer-events: none;
340+
box-sizing: border-box;
341+
`,
342+
serpMeasureHiddenMobile: css`
343+
position: absolute;
344+
left: -9999px;
345+
top: 0;
346+
width: 340px;
347+
visibility: hidden;
348+
pointer-events: none;
349+
font-size: 0.875rem;
350+
line-height: 1.5;
351+
`,
352+
serpReportSection: css`
353+
margin-top: 1rem;
354+
font-size: 0.875rem;
355+
color: ${t(colors.gray[700], colors.gray[300])};
356+
`,
357+
serpErrorList: css`
358+
margin: 4px 0 0 0;
359+
padding-left: 1.25rem;
360+
list-style-type: disc;
361+
`,
362+
serpReportItem: css`
363+
margin-top: 0.25rem;
364+
color: ${t(colors.red[700], colors.red[400])};
365+
font-size: 0.875rem;
366+
`,
208367
devtoolsPanelContainer: (
209368
panelLocation: TanStackDevtoolsConfig['panelLocation'],
210369
isDetached: boolean,
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { Show, createSignal } from 'solid-js'
2+
import { MainPanel } from '@tanstack/devtools-ui'
3+
import { useStyles } from '../../styles/use-styles'
4+
import { SocialPreviewsSection } from './social-previews'
5+
import { SerpPreviewSection } from './serp-preview'
6+
7+
type SeoSubView = 'social-previews' | 'serp-preview'
8+
9+
export const SeoTab = () => {
10+
const [activeView, setActiveView] =
11+
createSignal<SeoSubView>('social-previews')
12+
const styles = useStyles()
13+
14+
return (
15+
<MainPanel withPadding>
16+
<nav class={styles().seoSubNav} aria-label="SEO sections">
17+
<button
18+
type="button"
19+
class={`${styles().seoSubNavLabel} ${activeView() === 'social-previews' ? styles().seoSubNavLabelActive : ''}`}
20+
onClick={() => setActiveView('social-previews')}
21+
>
22+
Social previews
23+
</button>
24+
<button
25+
type="button"
26+
class={`${styles().seoSubNavLabel} ${activeView() === 'serp-preview' ? styles().seoSubNavLabelActive : ''}`}
27+
onClick={() => setActiveView('serp-preview')}
28+
>
29+
SERP Preview
30+
</button>
31+
</nav>
32+
33+
<Show when={activeView() === 'social-previews'}>
34+
<SocialPreviewsSection />
35+
</Show>
36+
<Show when={activeView() === 'serp-preview'}>
37+
<SerpPreviewSection />
38+
</Show>
39+
</MainPanel>
40+
)
41+
}

0 commit comments

Comments
 (0)