Open nicoburns opened 1 year ago
Just to note that with bindings to C++ (or technically Objective-C, though would limit to iOS/macOS), it would become possible to create bindings for JSI (JavaScript Interface; a library originally designed by Meta and Microsoft for React Native).
JSI is a common interface for performing simple operations that make use of native data (e.g. calling functions, exposing HostObjects) on any JS engine. The idea is that instead of calling (for example) V8 APIs directly, you'd call the engine-agnostic JSI APIs and a corresponding V8 call would be made by the engine-specific implementation of the JSI.
As engine-specific implementations are already available for V8, JSC, and Hermes, it would allow exposing Taffy to each of them with reduced maintenance burden. The advantage over WASM is that it would work on JS engines not supporting WASM (even if only due to JIT being disabled, e.g. the App Store).
It's something I'd have an interest in helping with once C++ bindings were made! Spare time willing, of course.
I think, that pure C public interface (for FFI) is a key for making bindings for various other languages. It is common solution/strategy implemented in many projects, even in Yoga (written internally in C++, with C public interface, which used in Java/C#/JavaScript(WASM)/ObjC bindings)
I think, that pure C public interface (for FFI) is a key for making bindings for various other languages. It is common solution/strategy implemented in many projects, even in Yoga (written internally in C++, with C public interface, which used in Java/C#/JavaScript(WASM)/ObjC bindings)
Agreed that a C interface ought to be priority as it can serve as the foundation for the others (and more easily allow 3rd parties to bind to Taffy in lieu of 1st party bindings.)
@shirakaba Presumably C bindings would work for you?
Could the JSI bindings used by https://github.com/triniwiz/nativescript-mason be reused @shirakaba?
@shirakaba in the mason lib the iOS side is pretty much the c bindings you're looking for, wish I had a little more time to port it.
@triniwiz How come you're using cxx and jsi for Android and cbindgen and swift for iOS? They seem like completely different approaches...
It's due to how the JSI is setup in NativeScript for iOS but I'm thinking I could move things around to give me an ease up
Could the JSI bindings used by https://github.com/triniwiz/nativescript-mason be reused @shirakaba?
Oh, I hadn't realised that was @triniwiz's approach! Yeah, something exactly like that 😂🙇♂️
@shirakaba Presumably C bindings would work for you?
Presumably! Although I defer to Osei at this point as he seems to have got it bridged all the way to iOS/Android already.
Commenting here since I haven't seen it shared anywhere: I assume there should also be tools to navigate the layouts, rather than simply… lay them out?
To make any one of these layouts navigable via keyboard or controller, you need the ability to, at minimum:
To me, these kinds of inclusion make the most sense in this library, rather than any library that uses these trees, since they're fundamental properties of the tree itself. You can't simply lay out a second navigation tree, since you need to depend on the layout of the original tree; one simple example of this is flexbox, since that can affect whether an element is below or to the right of something, for example.
Sure, you can manually compute this data yourself by navigating the tree and checking the positions of the layouts, but that's super inefficient and I would expect anything consuming the layout data to be able to build a navigation tree at the same time as the layout tree.
Would be more than willing to help draft out the API for what this looks like and develop these features, but wanted to comment on the roadmap here first since these are pretty fundamental things that look missing to me.
@nicopap has done more investigation into this on the Bevy side, but I don't think taffy is the right place for this abstraction: that should be handled on the UI crate's side.
Okay, you think that taffy isn't the right place for this abstraction, but do you have any particular ideas how a UI crate would actually perform these operations by itself after using Taffy to generate a layout?
Like I mention, the goal isn't to be live-navigating the Taffy tree directly, but for Taffy to offer data in the generated layout on where nodes are laid out relative to each other that makes it easier for any potential UI library to generate their own navigation trees.
The only way you could do this currently, unless I'm missing something major from the API, is manually sorting the position information from the nodes yourself, which seems way less efficient than just having Taffy add in a bit of extra metadata on each node that includes that information as it's generating the layout. Since the positions of things can depend on flow, this also affects the resulting navigation tree (example I gave was buttons being vertically or horizontally stacked based upon a flex layout) and so that needs to be taken into account.
Hmm.... are you saying you want Taffy to output absolute positions rather than parent-relative positions? That is something that Taffy could feasibly do. Although we would likely do it as a pass over the data after existing computation had be completed (so it wouldn't be any more efficient than you doing it yourself).
Regarding actually having a "node above", "node to left" reference on each ndoe. I think the only way to do this in Taffy would also to manually sort the positions of the nodes. As things like absolute position can mean that a node's position isn't necessarily in any particular order. And I don't see how Taffy would compute relative positions between nested nodes. In fact, it doesn't seem obvious to me how to order such nodes at all.
The bigger problem from my perspective is that I don't think there is a single best way to do this. For example, I don't think it's usual to determine the next/previous focusable node by visual position in the document. I think it's usually done by tabindex, falling back to source order.
Taffy 0.4 (upcoming) does allow for either:
Which might make it a bit easier for you to implement any custom functionality you want on top of Taffy's tree.
For example, I don't think it's usual to determine the next/previous focusable node by visual position in the document. I think it's usually done by tabindex, falling back to source order.
Yep, that's it. Though strictly speaking, that's tab navigation rather than orthogonal navigation, which is still unsolved.
The bigger problem from my perspective is that I don't think there is a single best way to do this.
For sure. I've seen loads of attempts at implementing Spatial Navigation (previously having worked in Smart TV) and there are loads of ways to go about it, each with different strengths and weaknesses. Norigin Spatial Navigation to name one, the WICG's Spatial Navigation (implemented by Opera) to name another, and also Mozilla's Spatial Navigation. Then there are frameworks from the BBC and no end of in-house frameworks from other manufacturers (like Netflix).
Some take the approach of measuring and hit-testing, while others (I assume BBC's TAL) probably take an explicit numbered grid. There are lots of problems to solve like z-index
, modals, drawers, toasts, popovers, transparent container views, virtualised lists, spatial memory (going back and forth across the same path, remembering which route you came from) and at some point there comes a balance between handling all use-cases and... having an API worth using.
Given the amount of application-level context needed to handle the more complex cases, I do think it would be better handled by a framework that sits on top of Taffy, that has that full context. These days, I'd probably base upon the WICG implementation myself, though it does of course assume a DOM-capable JS environment (which of course is not necessarily what Taffy will be targeting).
Hmm.... are you saying you want Taffy to output absolute positions rather than parent-relative positions? That is something that Taffy could feasibly do. Although we would likely do it as a pass over the data after existing computation had be completed (so it wouldn't be any more efficient than you doing it yourself).
But wouldn't orthogonal navigation not really need the absolute positions, since relationships with parents are mostly preserved in children? While CSS supports much more complicated layout structure via weird operations like the position
property, my understanding was that Taffy wasn't trying to support these, and so you'd still understand things like:
And sure, there are other cases where you're right that you'd just have to sort things by hand, but I was under the impression that, at least part of generating the flow, you'd still be able to add at least some metadata to help out any potential UI library looking to leverage this information, even if it's only at the same nesting level and they'd have to manually compute beyond that level themself.
That said, the ability to add your own metadata to the tree does provide a good starting point for implementing this as something external to taffy that's still attached to the same tree, and it would be a good way to evaluate whether adding this into taffy itself would really make sense.
For example, I don't think it's usual to determine the next/previous focusable node by visual position in the document. I think it's usually done by tabindex, falling back to source order.
It would still be nice to, for example, have the ability to navigate nodes in a linear fashion without having to navigate the tree yourself. Of course, this could easily be done with a plugin, I think it would be nice to add some sort of helper on top of the tree structure that lets you navigate leaves with an iterator that stores its own stack.
Also just want to say thank you @shirakaba for the links on the different ways other folks have tackled this problem. It's certainly not an easy one to solve, and the main reason why I wanted to bring it up here rather than just filing specific issues is that I think there may be some way Taffy could help out with this, even though obviously a bulk of the work would still be on any UI engine that used the resulting layouts.
[ ] Kotlin/Java (for Android)
I am actually working on this in #705, hope it helps :)
I thought it might be useful to track possible future feature work in a more structured way (grouped into categories).
See also: the Taffy Project Board
Future
CSS / Web layout features
min-content
/max-content
/fit-content
forwidth
/height
grid-template
,grid-template-areas
andgrid-area
Non-CSS layout features
stretch
forwidth
/height
and possiblymargin
/inset
API Enhancements
FFI / Bindings for other languages