Replies: 3 comments 3 replies
-
|
I like the direction, but I would start with a deliberately narrow extension surface. The main risk is that a broad plugin API can accidentally make RSD’s invariants optional: spec-aligned behavior, predictable style resolution, low runtime cost, and cross-platform consistency. If extensions can hook every phase freely, core behavior becomes hard to reason about and hard to optimize. A safer first version could expose only a few stable contracts: I would avoid exposing “post-resolution mutation” too early unless the resolved style representation is already considered stable. That phase is likely where text inheritance, interaction states, font scaling, and platform differences become subtle. For a POC, createStrictDomExtension({
name: "a11y-native-props",
nativeProps: {
html.button: ["accessibilityRole", "accessibilityState"],
},
mapStyleProps: {
// extension-owned props -> standard/intermediate style
},
})I would also make extensions explicit at the app boundary, not implicit package side effects: configureReactStrictDOM({
extensions: [a11yExtension, nativeInteropExtension],
})That keeps the behavior auditable and makes it easier to answer “why does this prop/style work in this app?”. Longer term, an extension registry could be useful, but the first milestone should probably be: one or two core-maintained example extensions, tests proving they cannot break unrelated style resolution, and a clear policy for what is allowed to remain non-spec-compliant. |
Beta Was this translation helpful? Give feedback.
-
|
I made a list of possible use cases for extensions to validate possible approaches. native interopextensions are probably not needed here, but a lot can be achieved improving props passthroughbasically an escape hatch to passthrough certain props that are not valid according to web spec, but are needed on the native side. This is likely simple in terms of implementation, but could be quite complex in terms of typing...
svg supporthttps://github.com/efoken/react-strict-dom-svg is overall a good approach here, alternative approaches can be explored in parallel without affecting each other. The question is what utilis are missing to make it easier to maintain and behave more correctly?
resize observer / intersection observerGlobal methods often require to use native refs as arguments (being it the actual DOM node on web or the react-native element ref). For the case of IntersectionObserver the problem is very relevant as it is now an avaialble API in the newe version of RN.
html.dialog
input type datekind of similar to Would be nice to avoid the patch and implement such sub-optimal polyfills as small extensions.
css animationswhat if #428 could be done as an extension?
container queries
dogfooding (transitions, interactive states, media queries, etc.)Ideally the same abstractions used to hook into various phases should be used to implement most of the core capabilities. That would make the code more modular and possibly help with testing and benchmarking in isolation each step with some generic utilities for "extensions" missing eventsMany DOM events are not currently available. Polyfilling them via extensions may be challening, but could be possible if we can inject context providers, allowed props, and hook into different phases. But I'm likely missing many steps and oversimplifying, thise could be a stretch goal and realistically could be simpler to contribute directly to core when possible. variable font custom polyfillIt may take a long time for RN to support variable fonts. For our use case we are currently patching react-strict-dom to mark the style keys as valid, then intercepting them to map certain typographic combinations to static font cuts (at runtime with a hacky in between component to be used in place of any normal alternative styling layer (classNames, props, etc.)While RSD is currently highly coupled with stylex, in theory it could benefit in using a intermediate typed representation of "styles". Stylex could be responsible of translating the user style authoring input (css.create) into the intermediate format that RSD is able to transform and use for building cross platform elements. This could potentially allow to iterate with other css input methods (e.g. classNames with actual css files parsed at built times, tailwind strings like in nativewind, atomic props like in tamagui, etc.) I tried to order those use cases base on complexity of what is missing, it may help identifying smaller scopes to possibly explore, but I'm also curious to hear your thoughts on each one. I can imagine that some of them could instead be better candidates for direct core contributions, or other may also work well as fully isolated packages, but may have to think about the specific details and see if different approaches can be validated against them. |
Beta Was this translation helpful? Give feedback.
-
|
Trying to summarize some possible next steps. I think for the short term there are some quick wins that would not require a full blown extension API yet:
cc @martinbooth do you have any input/concern on these thing and/or a specific API in mind? Otherwise I can find some time and make a draft PR to continue the discussion there. In a next or parallel phase we can explore how to allow / forward additional props to native. I think it could be relatively simple code wise, but It may get a bit tricky in terms of types, so I would prefer exploring it in a separate PR, and wonder if you have any concrete idea. For the mid/long term, for a full extension API, I feel we would need more discussions and possibly benchmark some competing approaches, we can use the list above to evaluate what needs what. I was also thinking that instead of allowing fully arbitrary extensions we could for example merge to main placeholder for web specs already and console warn the unimplemented ones, while offering an API to override existing features (unimplemented or not), as long as they respect the typings, this is similar to what happens with unsupported CSS features. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I would like to start a conversation to assess how RSD can enable third party extensions. cc @martinbooth
related: #4 (comment)
Contribution to the core have a high friction (for good reasons) given the goal of adhere closely to web standards and avoid performance penalties and breaking changes.
This friction can be a problem when it comes to community adoption where, in many real world scenarios, there is a need for pragmatic short term solutions while long term goal are gradually implemented.
There are several use cases that could benefit the project:
On a high level I'm thinking of an extension API that allow to hook into different phases of the RSD lifcycyle
e.g. syntax extension (e.g. new props or styles) -> transform styles before resolution -> transform after resolution (e.g. after text inheritance, font scaling, interactive states, etc.)
RSD code is already structured in a way that could allow this kind of extensions and that's how certain capabilities work, the main difference would be exposing the API and move to "phases" injection rather than manual addition of the different transformations.
There are also some quick wins we could get in the short term, while gradually enabling more complex types of extensions, for example improving
compat.nativeto support mapped style props, allowing to forward native props to RSD element based on a contract defined by a well scoped extension (e.g. some a11y extension to bridge the existing gaps).Then subsequent phases can gradually allow things like adding polyfill for html.* elements, polyfill for css features, etc.
I'd like to hear your thoughts on this and eventually decide if is worth an exploratory POC, prioritizing quick wins like an improved
compat.nativeand a basic extension registry for simple use cases like forwarding props on a given platform.Beta Was this translation helpful? Give feedback.
All reactions