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.

Screenshot of error in VS code   showing name is not a supported attribute
TypeScript error on name attribute. Explaining this is not allowed here

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, or none. MDN
<dialog></dialog> onCancel and onClose
Event handlers for when a dialog is cancelled or closed. MDN
fetchPriority on <link /> and <script></script>
Hints to the browser whether to fetch the resource at high, low, or auto priority. MDN
blocking on <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 of string. 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 of string. MDN
capture
Now properly typed as "user" | "environment" instead of string on <input type="file"/>. MDN
inputMode
Now properly typed as an enum instead of string. MDN
translate
Now properly typed as "yes" | "no" instead of string. 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
ModifierKey type
getModifierState() now accepts a typed union of valid modifier key strings instead of string. MDN
InputEvent interface
onBeforeInput now properly typed with data: string instead of a generic FormEvent. MDN
onResize / onResizeCapture
Resize event handlers now included in DOMAttributes. MDN
Suspense name
Labels a Suspense boundary for React DevTools instrumentation — no HTML equivalent.
React.JSX namespace
React.JSX.Element is now available as an alternative to the global JSX.Element. The global JSX namespace is deprecated in favour of this scoped version.

Find more posts in the following categories

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.