How can I add dynamic open graph tags in React to a specific component?

I’m having an issue with dynamic og meta tags in my React/Next application with LinkedIn post inspector and Facebook debugger. The issue is that the metatags are being generated, but after the load and the crawlers don’t find them.

This is the Chrome Elements TAB with og
enter image description here

This is the Network TAB -> Response without og
enter image description here

This is my current code src/pages/share-property/index.tsx

import React from "react";
import Property from "components/Sharing/Property";
import { GetServerSideProps } from "next";
import { Buffer } from 'buffer';
import { NextPage } from 'next';
import Head from 'next/head'; // Import Head

interface PropertyData {
  companyName: string;
  tenantId: string;
  stage: string;
  firstName: string;
  imageUrl: string;
  headerText?: string;
  resolvedImageUrl: string;
  fullUrl: string;
}

interface Props {
  propertyData: PropertyData | null;
}

const IndexPage: NextPage<Props> = ({ propertyData }) => {
  const shareTitle = propertyData ? `${propertyData.companyName} - ${propertyData.headerText}` : 'Loading...';
  const shareDescription = propertyData ? `Check out this property update from ${propertyData.companyName}` : '';

  return (
    <>
      <Head>
        {/* Primary Meta Tags */}
        <title>{shareTitle}</title>
        <meta name="description" content={shareDescription} />
        <meta
          name="viewport"
          content="width=device-width, initial-scale=1.0, viewport-fit=cover"
        />

        {propertyData && (
          <>
            {/* Open Graph / Facebook */}
            <meta property="og:title" content={shareTitle} />
            <meta property="og:description" content={shareDescription} />
            <meta property="og:image" content={propertyData.resolvedImageUrl} />
            <meta property="og:url" content={propertyData.fullUrl} />
            <meta property="og:type" content="website" />
            <meta property="og:image:width" content="1200" />
            <meta property="og:image:height" content="630" />
            <meta property="og:image:alt" content={`Property image from ${propertyData.companyName}`} />
            <meta property="og:site_name" content={propertyData.companyName} />

            {/* Twitter */}
            <meta name="twitter:card" content="summary_large_image" />
            <meta name="twitter:title" content={shareTitle} />
            <meta name="twitter:description" content={shareDescription} />
            <meta name="twitter:image" content={propertyData.resolvedImageUrl} />
          </>
        )}
      </Head>
      {propertyData ? (
        <Property
          companyName={propertyData.companyName}
          tenantId={propertyData.tenantId}
          stage={propertyData.stage}
          firstName={propertyData.firstName}
          imageUrl={propertyData.imageUrl}
          headerText={propertyData.headerText}
          resolvedImageUrl={propertyData.resolvedImageUrl}
          fullUrl={propertyData.fullUrl}
        />
      ) : (
        <div>Loading property data...</div>
      )}
    </>
  );
};

export const getServerSideProps: GetServerSideProps<Props> = async (context) => {
  const { query, req } = context;
  const data = query.data as string;

  console.log("getServerSideProps is running");

  if (!data) {
    console.log("No data query parameter"); 
    return {
      props: { propertyData: null },
    };
  }

  try {
    const decodedData = JSON.parse(Buffer.from(data, 'base64').toString('utf-8'));
    const { companyName, stage, imageUrl, firstName = "", tenantId = "", headerText = "Property Update" } = decodedData;

    const origin = req ? `${req.headers['x-forwarded-proto'] || 'http'}://${req.headers.host}` : '';
    const fullUrl = `${origin}${context.resolvedUrl}`;

    const getAbsoluteImageUrlServerSide = (url: string) => {
      if (!url) return '';
      if (url.startsWith('http')) return url;
      if (url.startsWith('//')) return `https:${url}`;
      return `${origin}${url.startsWith('/') ? '' : '/'}${url}`;
    };

    const resolvedImageUrl = getAbsoluteImageUrlServerSide(imageUrl);

    console.log("Property Data:", {
      companyName,
      tenantId,
      stage,
      firstName,
      imageUrl,
      headerText,
      resolvedImageUrl,
      fullUrl,
    });

    return {
      props: {
        propertyData: {
          companyName,
          tenantId,
          stage,
          firstName,
          imageUrl,
          headerText,
          resolvedImageUrl,
          fullUrl,
        },
      },
    };
  } catch (error) {
    console.error('Error processing data in getServerSideProps:', error);
    return {
      props: { propertyData: null },
    };
  }
};

export default IndexPage;

src/components/Sharing/Property.tsx

import React from 'react';
import { Box, Typography, Button, Card, CardMedia, CardContent } from '@mui/material';
import Link from 'next/link';
import Head from 'next/head';
import styles from 'styles/ShareButton.module.scss';

interface PropertyProps {
  companyName: string;
  tenantId: string;
  stage: string;
  firstName: string;
  imageUrl: string;
  headerText?: string;
  resolvedImageUrl: string;
  fullUrl: string;
}

const Property = ({
  companyName,
  tenantId,
  stage,
  firstName,
  imageUrl,
  headerText = "Property Update",
  resolvedImageUrl,
  fullUrl,
}: PropertyProps) => {
  const getStageMessage = () => {
    switch(stage.toLowerCase()) {
      case 'under contract':
        return (
          <Typography variant="body1" sx={{ mb: 2 }}>
            This home was just placed under contract using{' '}
            <Link href={new URL('/', fullUrl).origin} passHref>
              <a target="_blank" className={styles.Link}>{companyName}</a>
            </Link>
          </Typography>
        );
      case 'under construction':
        return (
          <Typography variant="body1" sx={{ mb: 2 }}>
            This house is beginning its renovations using{' '}
            <Link href={new URL('/', fullUrl).origin} passHref>
              <a target="_blank" className={styles.Link}>{companyName}</a>
            </Link>
          </Typography>
        );
      case 'sold':
        return (
          <Typography variant="body1" sx={{ mb: 2 }}>
            This home has just been sold using{' '}
            <Link href={new URL('/', fullUrl).origin} passHref>
              <a target="_blank" className={styles.Link}>{companyName}</a>
            </Link>
          </Typography>
        );
      default:
        return null;
    }
  };

  return (
    <>
      {/* Rest of your Property component UI */}
      <Box className={styles.PropertyContainer}>
        <Card sx={{ mb: 3 }}>
          {resolvedImageUrl && (
            <CardMedia
              component="img"
              height="400"
              image={resolvedImageUrl}
              alt="Property image"
              sx={{ objectFit: 'cover' }}
            />
          )}
          <CardContent>
            {getStageMessage()}
            <Box className={styles.CTASection}>
              <Typography variant="body1" paragraph>
                If you want to invest in real estate, click here to learn more
              </Typography>
              <Button
                variant="contained"
                size="large"
                href={new URL('/', fullUrl).origin}
                target="_blank"
                sx={{ mt: 2 }}
              >
                Learn More
              </Button>
            </Box>
          </CardContent>
        </Card>
      </Box>
    </>
  );
};

export default Property;

I have read many posts about this, but none resolve my issue. Any observation about what I’m doing wrong. Thanks.

Detect syntax errors on service worker update

When calling navigator.serviceWorker.register() and:

  • There is an active service worker.
  • There is a NEW service worker available.
  • The NEW service worker has syntax errors.

then the promise returned will resolve with a ServiceWorkerRegistration pointing to the existing (old) service worker instead of rejecting with an error notifying about the syntax error. Apparently this happens by design, from the sources I’ve investigated (too many to mention here).

I have not found any way of detecting these errors, and I’ve tried the following and more:

  • Checking for the service worker state, to no avail because only the registration.active property exists, no registration.waiting or registration.installing are available.
  • Listening to the updatefound event (same problem).
  • Calling registration.update(), which works but it is a hack.

So far, the only clean solution I can think of is to use globalThis.addEventListener('error'…) on the service worker itself and then postMessage() to the main thread, setting up some message listening code. Frankly, this is too big for something that IMHO should work out of the box by rejecting the promise returned by register().

Am I missing something obvious? I cannot find anything about this on the Internet, and I’ve searching for information for two days. I even asked a couple of AI… Thanks a lot in advance!

Javascript not run in Edge, but works with Firefox

I developed some simple CGI to search some contents, and depending on the user’s choice, some additional options are hidden or displayed.
To control the latter I added some simple Javascript to manipulate style.display.

It works fine with current Firefox ESR, but doe snot work with current Microsoft Edge.
The script (e.g. for onChange) are not run.

Only in the browser console I find some messages like this:

/search/form.html?t=win;s=U:1  Unrecognized Content-Security-Policy directive 'noscript-marker'.
form.html:1  Refused to load the script 'http://.../telefon.js' because it violates the following Content Security Policy directive: "script-src-elem 'none'".

form.html:59  Refused to execute inline script because it violates the following Content Security Policy directive: "script-src-elem 'none'". Either the 'unsafe-inline' keyword, a hash ('sha256-ZGa/EeW+nrOuUaIZ7raUOPCcg4acs3ew01xN9Vf9yK0='), or a nonce ('nonce-...') is required to enable inline execution.

I’m kind of clueless; the script is rather primitive.

With in the head element I have <script src="/telefon.js" type="text/javascript"></script>.

The script that does not run is here:

<select name="s" id="i-s" onchange="check_options(this)">
<option value="K">Telefonbuch K</option>
<option selected="selected" value="U">Telefonbuch U</option>
</select>

And after the form I added an immediate call to set up the initial state like this:

<script>check_options(document.getElementById('i-s'))</script>

The start of the HTML is also rather straight forward (created by Perl CGI):

<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="de-DE" xml:lang="de-DE">
<head>
<title>Telefon</title>
<link href="/favicon.ico" rel="icon" />
<link href="/normal.css" rel="stylesheet" title="Normal Mode" type="text/css" />
<link alternate="1" href="/darkmode.css" rel="alternate stylesheet" title="Dark Mode" type="text/css" />
<script src="/telefon.js" type="text/javascript"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>

So what is causing this, and how can I fix it?

Is it possible to use the audio from SpeechSynthesisUtterance in AudioMotion?

In the browser (using JavaScript and SpeechSynthesisUtterance), I’m able to do text to speech. Now I’d like to represent the utterance generated as visual audio in something like AudioMotion. But libraries like AudioMotion need either a file or a stream as a source. I don’t see how to get an audio stream from the speech produced by SpeechSynthesisUtterance. Is this even possible?

Fixing Mediapipe.js Module Arguments Error

Error with Mediapipe Hands in React Vite Project: “Module.arguments to plain arguments error”

Hi there,

I am trying to integrate Mediapipe Hands into my React project using Vite, but I’m encountering the error “[Module.arguments to plain arguments error]” (see the screenshot below). The issue happens intermittently—sometimes the code works fine, and other times I get the error.

Steps to Reproduce:
Set up a new React Vite project.

Install the @mediapipe/hands package.

Write the code to initialize and process hand landmarks using Mediapipe.

Run the application and see the error.

Observations:
The error doesn’t always occur. Sometimes it works as expected, and other times it throws the error.

I’m using Vite for faster bundling, and it may be related to how Vite handles module imports and arguments.

My code:-

function useGestureRecognition({ videoElement, canvasElement }) {
const hands = useRef();
const camera = useRef();
const handsGesture = useRef([]);

const { processLandmark } = useKeyPointClassifier();

async function onResults(results) {
    if (canvasElement.current) {
        const ctx = canvasElement.current.getContext('2d');

        ctx.save();
        ctx.clearRect(0, 0, canvasElement.current.width, canvasElement.current.height);
        ctx.drawImage(results.image, 0, 0, maxVideoWidth, maxVideoHeight);

        if (results.multiHandLandmarks) {
            for (const [index, landmarks] of results.multiHandLandmarks.entries()) {
                processLandmark(landmarks, results.image).then((val) => (handsGesture.current[index] = val));
                const landmarksX = landmarks.map((landmark) => landmark.x);
                const landmarksY = landmarks.map((landmark) => landmark.y);
                ctx.fillStyle = '#ff0000';
                ctx.font = '24px serif';
                ctx.fillText(
                    CONFIGS.keypointClassifierLabels[handsGesture.current[index]],
                    maxVideoWidth * Math.min(...landmarksX),
                    maxVideoHeight * Math.min(...landmarksY) - 15
                );
                drawRectangle(ctx, {
                    xCenter: Math.min(...landmarksX) + (Math.max(...landmarksX) - Math.min(...landmarksX)) / 2,
                    yCenter: Math.min(...landmarksY) + (Math.max(...landmarksY) - Math.min(...landmarksY)) / 2,
                    width: Math.max(...landmarksX) - Math.min(...landmarksX),
                    height: Math.max(...landmarksY) - Math.min(...landmarksY),
                    rotation: 0,
                },
                    {
                        fillColor: 'transparent',
                        color: '#ff0000',
                        lineWidth: 1,
                    }
                );
                drawConnectors(ctx, landmarks, HAND_CONNECTIONS, {
                    color: '#00ffff',
                    lineWidth: 2,
                });
                drawLandmarks(ctx, landmarks, {
                    color: '#ffff29',
                    lineWidth: 1,
                });
            }
        }
        ctx.restore();
    }
}

const loadHands = () => {
    hands.current = new Hands({ locateFile: (file) => `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`, });
    hands.current.setOptions({
        maxNumHands: 1,
        modelComplexity: 1,
        minDetectionConfidence: 0.5,
        minTrackingConfidence: 0.5,
    });
    hands.current.onResults(onResults);
};

useEffect(() => {
    (async function initCamera() {
        camera.current = new Camera(videoElement.current, {
            onFrame: async () => {
                await hands.current.send({ image: videoElement.current });
            },
            width: maxVideoWidth,
            height: maxVideoHeight,
        });
        camera.current.start();
    })()

    loadHands();
}, []);

return {maxVideoHeight, maxVideoWidth, canvasElement, videoElement};

}

Dynamic image selection don’t work with quarto website

I have a quarto dashboard where the user can select an image from a dropdown and it will appear instantly. I use observable js for this, and I recently got some help to make it work and there is a MWE in github.

The dashboard renders fine, but then I wanted to host it on GitHub pages, and so I added a _quarto.yml file. All it contain is this:

project:
  type: website

Then I use GitHub actions to render it. But now the image don’t appear anymore, neither with GitHub actions or when rendered locally. I created a branch of the original MWE with the _quarto.yml file and the rendered output.

Any help with this would be much appreciated.

How to prevent iOS keyboard from covering input fields in a Next.js web application (layout is not fixed)?

I am making a webApplication in NextJs. I have to make it responsive for iPphone. The problem I am facing is when the user touches an input box it get disappears under the keyboard if the input is below portion of the screen. What should I do to fix this?

I am currently using direct javascript onFocus scroll workaround, but this not the best. I have to add it to every pages where the input field is available which is not dev friendly.

inputElement.addEventListener('focus', () => {
  window.scrollTo({ 
    top: inputElement.offsetTop - 50, 
    behavior: 'smooth' 
  });
});

Is there a way to really authenticate static files? [closed]

I am building a node js app with html and css as the frontend, i’ve gotten all my routes working, but using local host the dashboard which is supposed to be protected is still statically served, tho with dummy data, it only gets dynamic after a login.

I tried serving the styles statically in the node js app but that results a another problem entirely..i’m thinking if i should just use a library like react or a framework like vue js, static file serving is killing me

404 errors after using importmap with Rails 8

I have the following within my importmap.rb

pin 'core-js/stable', to: 'core-js--stable.js' #  @3.42.0

However, when I try to import that package into my application.js:

import 'core-js/stable';

this then produces a bunch of extra requests for files that I don’t have and thus cause 404s, for instance:

/modules/es.string.trim.js
/modules/es.string.trim-start.js
/modules/es.string.trim-end.js
etc

How can I use something like core-js/stable and make sure everything downloads as it should?

Scaling centered objects between two page layouts with differing margins and gutters

I have a set of graphical objects whose positions are defined relative to the center of a two-page spread. I need to convert them from one page layout to another, where each layout may have different:

  • Overall dimensions (total width and height of the two-page spread)
  • Outer margins (“bleed”)
  • Inner gutter (“spine”)

When an object is originally placed at the exact center of the source spread, it can end up shifted off-center in the target layout because the bleed and spine values change the effective content area. This misalignment occurs even when the overall spread dimensions match, since the differing margins and gutter alter how the center point maps between formats.

I first tried the simplest thing: scale every object’s x, y, width, and height by the ratio of targetSpreadWidth/baseSpreadWidth and targetSpreadHeight/baseSpreadHeight. I expected an object at x=0 (true center) to stay at x=0, but it shifted whenever bleed or spine differed.

Next I tried “normalizing” into the content box: subtracting bleed and half the spine from each coordinate before scaling, then adding them back after. I also experimented with a full affine translate→scale→translate around the content origin. No matter how I tweaked those calculations, a centered object still ended up with a non-zero x when margins or spine changed.

This is the current approach (simplified):

const baseFormat = {
  width: 654,
  height: 343,
  bleed: 19,
  spine: 6
};

const targetFormat = {
  width: 342,
  height: 185,
  bleed: 19,
  spine: 6
};

const objects = [
  { width: 250, height: 250, center: { x: 157, y: 0 } },
  { width: 200, height: 200, center: { x: -155, y: 0 } }
];

const scaleX = targetFormat.width / baseFormat.width;
const scaleY = targetFormat.height / baseFormat.height;

const scaled = objects.map(o => ({
  ...o,
  width:  o.width  * scaleX,
  height: o.height * scaleY,
  center: {
    x: o.center.x * scaleX,
    y: o.center.y * scaleY
  }
}));

Visually, you can see what currently happens using the data from the snippet above.

Pictured original above and converted below

Access to XMLHttpRequest ‘https://example.com’ from origin ‘https://example.com’ has been blocked by CORS policy:

Access to XMLHttpRequest at ‘https://pinterest-backend-omega.vercel.app/api/auth/login’ from origin ‘https://pinterest-clone-brown.vercel.app’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

Hi there, I am facing this issue continuously. Can anyone help me

Note: I am using Express

acquire token silently always giving the new access token

I’ve implemented a piece of code where I first generate a token, store it in localStorage, and then retrieve it from there in my fetch utility for backend API calls. However, no matter how many times I refresh the page, it always generates a new access token.

This is my route.tsx file

export const msalInstance = new PublicClientApplication(msalConfig);
const accounts = msalInstance.getAllAccounts();
if (accounts.length > 0) {
    msalInstance.setActiveAccount(accounts[0]);
}

msalInstance.addEventCallback((event: EventMessage) => {
    if (event.eventType === EventType.LOGIN_SUCCESS && event.payload) {
        const payload = event.payload as AuthenticationResult;
        const account = payload.account;
        msalInstance.setActiveAccount(account);
    }
});

export const router = createBrowserRouter([
    {
        path: '/',
        element: <App pca={msalInstance} />,
        children: [
            { path: '/', element: <Home /> },
        ],
    },
]);

This is my App.tsx file

function App({ pca }: AppProps) {
    const authRequest = {
        ...loginRequest,
    };

    return (
        <MsalProvider instance={pca}>
            <MsalAuthenticationTemplate
                interactionType={InteractionType.Redirect}
                authenticationRequest={authRequest}
                errorComponent={Error}
                loadingComponent={Loading}
            >
                <OutletWrapper />
            </MsalAuthenticationTemplate>
        </MsalProvider>
    );
}

const OutletWrapper: React.FC = () => {
    const { instance } = useMsal();
    const account = useAccount(accounts[0] || {});

    const [apiData, setApiData] = useState<AuthenticationResult | null>(null);

    useEffect(() => {
        if (account) {
            instance
                .acquireTokenSilent({
                    scopes: ['User.Read'],
                    account: account,
                })
                .then((response) => {
                    if (response) {
                        localStorage.setItem('authStatus', response.idToken);
                        setApiData(response);
                    }
                });
        }
    }, [account, instance]);

    if (!apiData) return <Loading />;

    return (
        <CompanySelectionWrapper>
            <Sidebar />
            <Outlet />
        </CompanySelectionWrapper>
    );
};

export default App;

Why does the submit button on the form not work when using CKEditor, even though the data from CKEditor is correctly moved into the hidden textarea?

here’s my console error notification
it’s happen when i try to upload my code, when i dd my data already sent but couldn’t upload to database.

create:1 An invalid form control with name='content' is not focusable. <textarea name=​"content" id=​"content" class=​"form-control" rows=​"5" required style=​"visibility:​ hidden;​ display:​ none;​">​</textarea>​

here my form code create.blade.php
i try to use CK Editor for my article content, but when i deactivate the CK Editor but when i try delete my JavaScript it works just fine.

<form action="{{ route('admin.articles.store') }}" method="POST" enctype="multipart/form-data" id="articleForm">
        @csrf    
<div class="mb-3">
            <label for="content" class="form-label">Content</label>
            <textarea name="content" id="content" class="form-control" rows="5" required style="visibility: hidden; opacity: 0;"></textarea>
            @error('content')
                <div class="alert alert-danger mt-2">{{ $message }}</div>
            @enderror

here’s my JS, at the end my create.blade.php

<script src="https://cdn.ckeditor.com/ckeditor5/36.0.1/classic/ckeditor.js"></script>
    
<script>
    let editorInstance;

    document.addEventListener('DOMContentLoaded', function () {
    ClassicEditor
        .create(document.querySelector('#content'))
        .then(editor => {
            editorInstance = editor;

            document.getElementById('articleForm').addEventListener('submit', function (event) {
              
                document.querySelector('textarea[name="content"]').value = editorInstance.getData();
            });
        })
        .catch(error => {
            console.error("Error initializing CKEditor:", error);
        });
});

here’s my laravel controller Store Function

    public function store(Request $request)
{
    // Debugging: Dump the received request data
    dd($request->all()); // Debugging: Show all request data

    Log::info('Data yang diterima:', $request->all());

    // Validate the incoming data
    $validatedData = $request->validate([
        'title' => 'required|string|max:255',
        'content' => 'required|string',
        'author' => 'required|string',
        'published' => 'boolean',
        'meta_description' => 'nullable|string|max:255',
        'tags' => 'nullable|string|max:255',
        'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
    ]);

    // Handle image upload if exists
    $imagePath = null;
    if ($request->hasFile('image')) {
        $imagePath = $request->file('image')->store('articles', 'public');
        Log::info('Image uploaded successfully:', ['image_path' => $imagePath]);
    }

    // Create and save the article
    $article = new Article();
    $article->title = $validatedData['title'];
    $article->content = $validatedData['content'];
    $article->author = $validatedData['author'];
    $article->published = $validatedData['published'] ?? false;
    $article->meta_description = $validatedData['meta_description'];
    $article->tags = $validatedData['tags'];
    $article->image = $imagePath;
    $article->save();

    return redirect()->route('admin.articles.index')->with('success', 'Article created successfully.');
}

Leaflet map doesn’t render, missing some parts

After rendering leaflet component in my angular app some map-images are missing, here is my code

import { Component, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { DOCUMENT } from '@angular/common';



@Component({
  selector: 'app-leaflet-offline-maps',
  standalone: true,
  imports: [],
  templateUrl: './leaflet-offline-maps.component.html',
  styleUrls: ['./leaflet-offline-maps.component.css']
})
export class LeafletOfflineMapsComponent {
  private isBrowser: boolean;

  constructor(
    @Inject(PLATFORM_ID) private platformId: Object,
    @Inject(DOCUMENT) private document: Document
  ) {
    this.isBrowser = isPlatformBrowser(platformId);
  }

  async ngOnInit(): Promise<void> {
    if (this.isBrowser) {
      const L = await import('leaflet'); 

      const map = L.map('map').setView([42.4304, 19.2594], 13);

      L.tileLayer('http://localhost:8080/tile/{z}/{x}/{y}.png', {
        attribution: '© OpenStreetMap contributors'
      }).addTo(map);
    }
  }
}

and

<div id="map"></div>

enter image description here

also I already installed leaflet and import leaflet css style in angular.json

How to make tab skip the icon inside the Time Picker?

What I have

I have a MUI Time Picker component inside React.

Goal

I would like to modify the tabbing behavior. By default if the user fills out the input and presses Tab the focus will jump to the clock icon inside the time picker. This is unnecessary since that icon is only needed when the user uses the mouse. After the input is filled via keyboard Tab should jump to the next field. The default behavior requires the user to press Tab twice which slows down usage through the keyboard.

What I tried

I have a basic TimePicker. I just want to know how to configure it:

<TimePicker label="Basic time picker" />

Problem

Usually the API docs list a lot of customization options but tab behavior doesn’t have a prop.