One Dependency Update Unlocks 4 Years of HTML Attributes in SPFx 1.23
SharePoint Framework 1.23 was released recently, but it’s already outdated. Not all of it, but sometimes it feels like Microsoft is afraid to update its dependencies, even though they fall in the same major or minor version.
Why should I care about @types/react?
HTML and CSS were mostly static ten years ago. That’s no longer true. The pace of new HTML and CSS features has accelerated significantly. Relying on a four-year-old type definition doesn’t hold up.
Without an updated type definition, you end up writing custom type declarations for HTML that your browser has supported for years.
What is the impact of upgrading the React types to a newer version?
Zero runtime impact. Zero React version change. Just TypeScript, finally aware of the HTML you were already allowed to write.
It matters a lot because you can write cleaner browser code with less JavaScript in some cases. You’ll find a complete list of benefits at the end. For now, let me explain what the type update solves using an accordion component.
Practical example: Accordion
Accordions are good for making complete sections collapsible on demand. Especially in mobile scenarios, they are really popular.
What many people don’t know is that they require no JavaScript to function correctly. In 2016, two new elements were introduced: <details> and <summary>, combined to form an accordion. Used this way, an accordion has basic accessibility built in. No focus traps, no ARIA required, and you can style it however you like.
See the Pen Basic Accordion by Stefan Bauer (@StfBauer) on CodePen.
It is a basic accordion in which each item opens individually. Adding the HTML attribute open allowed you to open dedicated elements by default.
In late 2024, another feature was added to <details>/<summary> accordions. By assigning the same value to the name attribute on multiple <details> elements, you get an exclusive accordion.
See the Pen Basic Accordion by Stefan Bauer (@StfBauer) on CodePen.
I added name=”spfx-faq” to each element above, and you can see how the behaviour has changed. Assigning the name attribute with the @types/react version that SharePoint Framework ships with would throw a TypeScript error.

You can patch it manually by creating the following file in the source folder now.
// src/react-augmentation.d.ts
import 'react';
declare module 'react' {
interface DetailsHTMLAttributes<T> extends HTMLAttributes<T> {
name?: string;
}
}
It works, but it is not efficient. A single update of @types/react to version 17.0.91 has the same effect across the entire project.
Already using PnP Reusable Components for accordions?
PnP Reusable Components ships two accordion controls. A regular one and an “accessible” one. Both were the right solution when they were built. Both rely on JavaScript and third-party libraries. Neither uses <details> or <summary>.
The accessible accordion was built following the W3C accessible accordion pattern — specifically this example. That pattern exists to fill a gap that predates reliable <details>/<summary> browser support. The gap no longer exists. The library it is based on, react-accessible-accordion, was deprecated by its own maintainers for exactly this reason. Native HTML now does the job.
These controls were right when they were built and aged well over time. That said, hTWOo, by me and Julie Turner has always used <details> and <summary> as the foundation for its accordion component. With the updated @types/react version, SPFx projects can now use the name attribute directly, unlocking exclusive accordion behaviour without any JavaScript, any third-party library, or any workaround.
Verdict
The outdated type definition may even explain why SharePoint’s own collapsible sections don’t use <details> and <summary>. That would make it a problem Microsoft created for themselves.
I would not recommend updating any dependency that affects the runtime. Updating from React 17 to React 18 may work, but it is more likely to have negative consequences in an SPFx project.
Type definitions are different. They only tell TypeScript what attributes are valid. Nothing changes at runtime. It is safe to update @types/react anywhere within the 17.x range — from 17.0.0 up to 17.0.91, the current latest version.
What you should not do is cross the major version boundary. Upgrading the React types to 19.2.14, for example, would not work with SPFx 1.23.
It is a common pattern for Microsoft to ship an outdated version of npm packages. They follow a static version approach and do not trust that newer versions, at least minor ones, work with their code.
In this case, a four-year-old type definition is more of a bummer than a safeguard.
Haven’t upgraded to Heft yet? This AI prompt saved me a lot of hours and was safer to use than a manual upgrade.
In the appendix, you will now find, as promised, the full changeset.
Appendix: What changed between @types/react 17.0.45 and 17.0.91
This has changed between those two versions.
<details>name- Groups
<details>elements into an exclusive accordion — open one, the others close automatically. MDN <dialog></dialog>closedby- Controls how a dialog auto-dismisses:
any,closerequest, ornone. MDN <dialog></dialog>onCancelandonClose- Event handlers for when a dialog is cancelled or closed. MDN
fetchPriorityon<link />and<script></script>- Hints to the browser whether to fetch the resource at high, low, or auto priority. MDN
blockingon<link />and<script></script>- Explicitly marks a resource as render-blocking. MDN
part- Exposes a shadow DOM element for external CSS styling via
::part(). MDN exportparts- Transitively exports shadow parts to ancestor DOMs. MDN
enterKeyHint- Sets the action label on the virtual keyboard Enter key — useful for mobile form UX. MDN
autoCapitalize- Now properly typed as an enum (
"off" | "none" | "on" | "sentences" | "words" | "characters") instead ofstring. MDN autoFocus- Moved to
HTMLAttributes— now applies consistently to all elements instead of being scattered across individual element interfaces. MDN nonce- Moved to
HTMLAttributes— now available on all elements for Content Security Policy support. MDN crossOrigin- Now properly typed as
"anonymous" | "use-credentials" | ""instead ofstring. MDN capture- Now properly typed as
"user" | "environment"instead ofstringon<input type="file"/>. MDN inputMode- Now properly typed as an enum instead of
string. MDN translate- Now properly typed as
"yes" | "no"instead ofstring. MDN aria-braillelabel- Sets a braille-specific label for assistive technology. MDN
aria-brailleroledescription- Abbreviated braille role description for assistive technology. MDN
aria-description- Inline string description, alternative to
aria-describedby. MDN aria-colindextext- Human-readable alternative to
aria-colindex. MDN aria-rowindextext- Human-readable alternative to
aria-rowindex. MDN ModifierKeytypegetModifierState()now accepts a typed union of valid modifier key strings instead ofstring. MDNInputEventinterfaceonBeforeInputnow properly typed withdata: stringinstead of a genericFormEvent. MDNonResize/onResizeCapture- Resize event handlers now included in
DOMAttributes. MDN Suspensename- Labels a Suspense boundary for React DevTools instrumentation — no HTML equivalent.
React.JSXnamespaceReact.JSX.Elementis now available as an alternative to the globalJSX.Element. The globalJSXnamespace is deprecated in favour of this scoped version.