00:00:08.760
okay can you hear me now yeah it's like
00:00:11.240
on a
00:00:12.400
podcast uh hey everyone it's great to be
00:00:15.799
here and to see so many of my friends um
00:00:19.760
at my first ever yuu what an awesome
00:00:22.720
conference I'm Joel I'm a software
00:00:25.000
engineer from Oxford in the UK uh and
00:00:27.880
I've got about 30 minutes to cover at
00:00:29.640
least 45 minutes of content so we might
00:00:32.239
have to go at
00:00:34.760
1.5x you're okay with that right you
00:00:37.640
listen to podcast and you're not an
00:00:40.039
animal so in the run up to the
00:00:43.000
conference I got an email from the
00:00:45.320
organizers and it
00:00:47.360
said we also have a backup machine
00:00:49.600
available in case of technical issues
00:00:51.480
feel free to share your slides at least
00:00:53.399
one week before the event with
00:00:57.359
us so if we have any technical issues
00:00:59.600
today then I've got nothing for you it's
00:01:03.079
cute that they thought I'd have slides
00:01:04.560
ready this is me preparing for
00:01:08.600
yuku and this is me doing open
00:01:12.720
source I can't help it so here's the
00:01:15.439
thing about ADHD there's a spectrum that
00:01:17.799
runs from easily distracted via
00:01:19.759
functional adult to
00:01:21.920
hyperfocused so I operate here and here
00:01:26.640
and it's binary
00:01:30.320
the only way I can stay on track and get
00:01:32.280
anything done is to constantly nerd
00:01:34.119
snipe myself there are loads of tricks
00:01:36.720
and techniques uh to nerd snipe yourself
00:01:38.920
into doing things um even boring things
00:01:41.720
think about how you'd nerd snipe someone
00:01:43.159
else I wonder if it's possible to do
00:01:45.920
insert difficult thing I bet you
00:01:47.799
couldn't insert difficult
00:01:50.840
thing uh the key is the thing has to be
00:01:54.680
challenging and high quality essentially
00:01:57.880
it's about aiming higher
00:02:00.159
have you ever heard the phrase perfect
00:02:02.399
is the enemy of the good it's kind of
00:02:05.000
nonsense if you think about it because
00:02:06.719
compromise is the enemy of
00:02:09.599
motivation I think humans want to do a
00:02:11.760
really good job doing hard things really
00:02:14.840
well is much easier in some ways than
00:02:16.760
doing easy
00:02:18.800
things just want to open
00:02:28.640
this so
00:02:32.239
so people talk about 10x Engineers this
00:02:35.400
idea that some Engineers are 10 times
00:02:37.519
better than average some dismiss it as
00:02:40.760
nonsense I think 10x Engineers are real
00:02:43.879
but it's not the engineers themselves
00:02:45.640
and it's not even the problems that
00:02:46.840
they're solving so much as the way that
00:02:48.760
they're working on them 10x Engineers
00:02:51.200
are just regular Engineers who are
00:02:52.599
locked in they're nerd sniped you can't
00:02:55.680
change your boring business problems but
00:02:57.319
you can aim higher in terms of how you
00:02:58.920
solve them here's an example I think the
00:03:01.560
team at Zed the text editor are probably
00:03:04.040
some of the most productive engineers in
00:03:05.480
the world they ship and I think a large
00:03:08.640
part of the reason they do this is
00:03:10.200
because they're so ambitious they're
00:03:11.920
trying to build the best text editor in
00:03:13.560
the world and they'll move mountains to
00:03:15.000
do it for example they designed a
00:03:17.680
completely new UI framework that runs on
00:03:19.319
this GPU at 120 frames a second like a
00:03:22.840
game I think your average manager would
00:03:24.920
have said that this was Reinventing the
00:03:26.640
wheel something you're not meant to do
00:03:30.080
um something that will slow you down and
00:03:32.879
distract you from the real
00:03:34.720
task so I'm here to talk about building
00:03:37.280
beautiful views in Ruby before we get
00:03:39.879
into that I have some questions for you
00:03:42.080
um just want to kind of gauge who I'm
00:03:43.640
talking to so who loves reading and
00:03:46.040
writing
00:03:48.319
Ruby okay that's pretty much everyone
00:03:52.439
um how many of you would say it's your
00:03:54.599
favorite computer
00:03:57.360
language second favorite
00:04:00.640
top
00:04:01.879
three
00:04:04.319
okay it's top two for
00:04:07.040
me um but I won't tell you what the
00:04:09.079
other one is okay it's
00:04:12.439
CSS um people have very strong opinions
00:04:15.000
on these things I have a lot of strong
00:04:16.320
opinions too and for the next 25 minutes
00:04:18.519
I've got a microphone so strap in Jimm's
00:04:21.720
maybe
00:04:23.919
rustled why do I love
00:04:26.120
Ruby I love Ruby because it's so
00:04:28.360
flexible I find it natural to express
00:04:30.639
ideas and create abstractions in Ruby
00:04:33.440
Ruby is in its own league for this stuff
00:04:35.440
it's like nothing else what do I mean by
00:04:38.039
creating abstractions this is quite
00:04:40.360
difficult to explain it's about finding
00:04:42.120
Concepts and giving them really good
00:04:43.440
names and interfaces and then moving
00:04:45.160
them away reducing your
00:04:47.120
dependencies I like to think of these
00:04:49.320
Concepts as sort of existing whether we
00:04:52.680
codify them or not the concept of
00:04:55.520
administration ship probably exists in
00:04:57.520
your app even if you don't have an
00:04:58.919
Administration ship model and you
00:05:00.960
probably
00:05:02.639
should so it's about naming things we
00:05:05.800
start with basic logic gates we build
00:05:07.520
layer by layer on top of that First
00:05:09.080
Assembly then C then Ruby somewhere in
00:05:11.199
the middle and Ruby has objects and
00:05:12.800
variables garbage collection floats
00:05:14.479
integers arrays and strings there ranges
00:05:16.840
innumerables modules and
00:05:19.720
classes but this is just the middle of
00:05:21.720
the stack of
00:05:23.000
abstraction on top of Ruby you're using
00:05:25.080
Frameworks rails and other libraries and
00:05:27.160
finally you have your own abstractions
00:05:28.680
for your domain
00:05:30.400
you might be thinking doesn't that make
00:05:31.479
a mess with all these abstractions how
00:05:33.280
do you know what's going on it's amazing
00:05:36.160
how many times I've seen this attitude
00:05:38.639
but it's kind of like saying with all
00:05:40.319
these drawers and boxes to organize your
00:05:42.080
Lego kids how do you know where anything
00:05:43.720
is wouldn't it be easier if you just
00:05:44.800
threw it all on the
00:05:45.960
floor words that have never been spoken
00:05:48.280
by a parent in all of
00:05:50.120
history some of you were told that
00:05:53.039
duplication is better than the wrong
00:05:55.639
abstraction I think that's
00:06:02.240
there is no wrong
00:06:04.319
abstraction and doing the wrong
00:06:06.280
abstraction today if you're abstracting
00:06:08.560
well will make it easier to change later
00:06:10.319
not more difficult even if it turns out
00:06:12.479
you need to change the abstraction as
00:06:14.240
requirements change you know what's
00:06:16.599
difficult to
00:06:18.400
change lots of code is difficult to
00:06:20.960
change well okay that's true too but
00:06:23.840
what I mean is more code is more
00:06:25.919
difficult to change than less code if
00:06:28.319
you have 20 independent implementations
00:06:30.280
of the same thing that thing is not easy
00:06:32.639
to change so that's why I like Ruby it's
00:06:35.479
flexible when it comes to making
00:06:36.680
abstractions recognizing innate Concepts
00:06:38.919
and codifying them ultimately making
00:06:41.680
things more consistent and easier to
00:06:52.639
change speaking of strong opinions
00:06:56.199
what's your opinion on
00:06:58.240
Tailwind I was in two minds about this
00:07:00.639
for a
00:07:02.560
while to understand why let's look at
00:07:05.039
how I learned to write frontend code
00:07:06.479
when I first got into this stuff so
00:07:08.879
here's a pretty typical example of
00:07:10.160
what's often called semantic class names
00:07:13.319
by naming these Concepts we make them
00:07:14.800
reusable five distinct Concepts five
00:07:17.680
names kind of ties back to why I like
00:07:19.840
Ruby right did any see Adam Wan's talk
00:07:23.759
at rails world can you imagine his
00:07:26.240
reaction when he saw action View
00:07:31.280
propser Adam he did a great job of
00:07:32.720
explaining how you can use apply to
00:07:34.520
Wrangle semantic classes from tailwind
00:07:36.800
and his talk was great it always amazes
00:07:38.560
me how fast he can move in Tailwind
00:07:40.000
designing in the browser if you look at
00:07:42.199
the Tailwind website it actually
00:07:43.400
recommends multic cursor editing as a
00:07:45.240
way to handle duplication I'm not saying
00:07:47.599
this is very wrong but it's definitely
00:07:49.919
questionable if we look at another one
00:07:51.639
of Adam's projects headless UI you'll
00:07:53.560
see something like this this is view by
00:07:56.400
the way the utility classes are hidden
00:07:58.639
in the implementation of these named
00:08:01.120
components so my story with Tailwind
00:08:03.720
kind of went like
00:08:09.080
this Flex Flex is a library for
00:08:12.280
Designing objectoriented components in
00:08:15.240
Ruby it isn't a templating language
00:08:18.120
though it does have templating features
00:08:20.280
but the templating inlex is structural
00:08:22.479
it is not string
00:08:23.720
based it's also not just a DSL for
00:08:26.080
creating HTML there have been a bunch of
00:08:28.080
these over the years it all shapes and
00:08:29.479
exes and flex does draw inspiration from
00:08:31.720
many of them but Flex is also quite
00:08:33.880
different from these gems it's quite
00:08:35.800
unique so my goal today is to give you a
00:08:38.159
small taste of what's possible so you
00:08:40.279
can decide to either try it out or that
00:08:42.240
it's definitely not for
00:08:44.640
you so the heart of flex is this direct
00:08:47.560
mapping of HTML semantics to Ruby syntax
00:08:52.320
HTML has elements those are mapped to
00:08:54.600
methods it has attributes which are
00:08:56.480
mapped to keyword arguments you can also
00:08:58.320
Nest elements inside other elements and
00:09:00.320
that's all handled on the Ruby side with
00:09:02.560
blocks I love HTML but HTML syntax is
00:09:06.240
just one way to represent HTML semantics
00:09:09.320
as you'll see later there are some real
00:09:10.959
advantages to embracing this native
00:09:12.600
mapping in
00:09:13.760
Ruby however some people really don't
00:09:16.079
like it that's kind of okay here's a
00:09:19.440
some people don't like Ruby here's a
00:09:21.600
real tweet from a couple of days
00:09:25.240
ago this looks gross this Flex thing
00:09:27.680
it's so unintuitive makes me cringe I
00:09:30.160
told you Jim would be
00:09:34.760
rustled so let's look at some of the
00:09:36.680
features quickly um and then we'll get
00:09:38.720
into a demo uh Flex is designed to
00:09:41.839
structurally prevent cross-site
00:09:43.120
scripting taxs by default so if you have
00:09:45.440
a link with an href from user data Flex
00:09:48.079
knows that it's a link and will ensure
00:09:49.519
there's no JavaScript in it how many of
00:09:52.360
you really use a Content security policy
00:09:54.920
that disallows unsafe
00:09:58.079
inline since isolation Flex components
00:10:00.680
only depend on the data you pass in
00:10:02.600
making them easy to test and reuse it
00:10:05.480
also ships with test helpers for
00:10:06.800
capibara naguri noer and mini test and
00:10:11.640
aspec it has no dependencies and the
00:10:13.959
rails extension only depends on Rails
00:10:15.720
itself technically rail tie Flex can
00:10:18.800
stream responses um so bringing um time
00:10:22.320
to First Bite down in some case users
00:10:24.880
can see the first static content
00:10:26.360
rendered in their browser before the
00:10:28.279
database has even respond
00:10:29.839
responded you can render a view
00:10:31.640
targeting a specific set of Dom IDs and
00:10:34.079
flex only does the work to render just
00:10:35.639
the parts you want so this is great for
00:10:37.959
partial Hotwire updates like turbo
00:10:40.279
frames there's no time wasted rendering
00:10:42.959
the bits of the page that you don't want
00:10:44.720
and it doesn't send the bites over the
00:10:47.040
wire you can also package components up
00:10:49.440
into kits for easy reuse across projects
00:10:52.320
kits can be shared with the community as
00:10:54.279
ruby gems or kept for internal use
00:10:57.320
here's a few examples uh of third party
00:11:01.160
uh libraries of components Flex UI
00:11:03.120
protos and zest UI all built on
00:11:05.839
Flex it's also fast enough Flex renders
00:11:08.279
at about 1 gbits per second on my
00:11:11.040
MacBook Pro uh and it doesn't slow down
00:11:13.760
the more components you extract there's
00:11:15.519
no need to cach the
00:11:17.399
view Flex works great with rails
00:11:19.680
supports all rails helpers and plays
00:11:21.040
nicely with view component action view
00:11:23.000
stimulus turbo and Tailwind you can
00:11:25.279
render view components and action view
00:11:26.839
partials in flex and the other way
00:11:28.800
around
00:11:30.720
and it's just Ruby so you can use your
00:11:32.639
existing skills and Dev tools things
00:11:34.839
like Ruby LSP solar graph ruop simple C
00:11:38.600
Ruby mine they all
00:11:41.040
work so what is a component let's look
00:11:44.440
at a typical web
00:11:46.399
app
00:11:48.680
uh there are 54 icons above the fold I
00:11:52.880
think each one of these is a component
00:11:55.720
called icon I think that makes sense
00:11:58.160
they're all different in is of the same
00:11:59.920
kind of
00:12:00.959
object 14 badges there are 13 buttons
00:12:06.000
two avatars a header a file explorer a
00:12:10.079
sidebar a
00:12:13.360
menu this is the point where I have to
00:12:16.199
switch my laptop
00:12:19.279
to uh mirror my
00:12:29.320
my display
00:12:32.000
okay uh so for a live
00:12:36.079
demo me go full screen on
00:12:38.639
this um so I don't have time to show you
00:12:41.680
flex and rails but this is a quick demo
00:12:43.760
of uh some of the basic
00:12:45.880
features um so we start with a class uh
00:12:49.480
this one's just called example and here
00:12:51.680
we're rendering a heading and turns into
00:12:54.680
H1 pretty
00:12:56.399
simple uh I can I have this kit called
00:13:00.480
components which is just a module that
00:13:02.880
extends Flex kit and I can include that
00:13:06.959
module I just put an o
00:13:14.279
in and now I can use uh components so I
00:13:17.920
have a component called
00:13:23.399
nav so our nav component is wrapping
00:13:26.519
this heading uh in
00:13:30.279
Navar and we don't specify any details
00:13:33.839
about this nav from uh from this example
00:13:36.480
component that the class menu has been
00:13:39.079
added in the example in the nav
00:13:42.720
component which looks like this so
00:13:46.000
that's basic
00:13:47.440
wrapping um let's get back to the
00:13:49.680
example and I'm going to add some links
00:13:54.160
so let's say I want something like a and
00:13:57.000
we'll call this class nav
00:14:00.959
and I'm going to add a
00:14:04.000
HF and we'll just put it to slash I'll
00:14:07.600
say
00:14:13.320
home now this isn't
00:14:17.600
great the example component now um oh
00:14:23.480
I've got that in the wrong place the
00:14:25.600
example component now um knows how to
00:14:28.519
render
00:14:30.199
items uh and I don't think this is
00:14:32.480
amazing just going to save
00:14:35.079
this uh it shouldn't really know the
00:14:38.279
details of like the CSS class here or
00:14:40.839
that nav items need to be an a tag maybe
00:14:43.120
they need to be wrapped in a div or An
00:14:44.839
Li so we can take this implementation
00:14:48.440
and we can move it into the nav
00:14:50.680
component and we just Define a method
00:14:52.880
here called iton and we'll take uh the
00:14:57.519
text and we'll take the
00:15:02.199
hre we're going to replace this href
00:15:05.320
with nothing and we'll just put the
00:15:09.120
text
00:15:12.839
here so now um back in our
00:15:17.040
example uh we
00:15:19.839
can pick up the yielded
00:15:23.440
nav and we can do n. item remember we
00:15:27.240
had text followed by
00:15:29.720
the
00:15:30.880
link so now this implementation detail
00:15:35.120
and I'm I'm using semantic classes here
00:15:36.720
but you could use tell in classes is
00:15:39.720
completely encapsulated in the nav
00:15:43.240
component there's nothing leaking
00:15:45.560
outside of this and there's no
00:15:47.959
duplication and I don't know why I keep
00:15:49.800
switching to the wrong
00:15:52.920
tab so uh let's look at another example
00:16:01.440
tabs I've got a component called tab
00:16:03.920
group and it does the same
00:16:06.240
thing gives me uh T and I can do t. tab
00:16:10.720
I'm going to give it a name let's call
00:16:12.519
it tab a and I can give it some content
00:16:15.959
let's put a p in here and let's say
00:16:21.000
hello so as you can see similar kind of
00:16:24.120
thing is happening we've got tabs oh why
00:16:26.040
does it do that we got tabs we got tab
00:16:28.079
link and we got tab content and I can do
00:16:30.680
this multiple times let's change that to
00:16:35.440
B and we're doing that for multiple
00:16:38.920
tabs but what if we wanted
00:16:42.680
to have both the links rendered at the
00:16:47.360
top followed by both sets of
00:16:50.519
content the way that this is working
00:16:52.480
right now is we start rendering the the
00:16:55.600
tab group component and let me just
00:16:58.319
switch into tab
00:17:00.800
group um we hit the view template it
00:17:04.319
receives a block it creates this div
00:17:06.839
with the class of tabs and it passes the
00:17:09.039
Block
00:17:10.160
in this default implementation is
00:17:13.600
essentially the same as if we just did
00:17:16.799
yield except Flex automatically makes it
00:17:19.600
yield self unless we give it a explicit
00:17:23.439
argument so when we yield control is
00:17:26.679
given back to the caller which is
00:17:29.520
uh
00:17:30.919
here and um so this allows us to hit
00:17:34.280
this tab method multiple times while
00:17:36.600
it's
00:17:39.039
rendering and as you can see we're just
00:17:41.400
outputting this so if we wanted to
00:17:44.000
Output both sets of links followed by
00:17:46.320
both sets of content we're going to have
00:17:48.160
to do something different this will this
00:17:49.320
isn't going to work so the way that I
00:17:51.200
would solve this is I would first create
00:17:54.919
um a record for our tab so something
00:17:58.400
like tab is data. Define it has a name
00:18:02.559
it has
00:18:04.200
content uh now we want to have a list of
00:18:12.320
tabs and we want to update this uh tab
00:18:15.840
method to push into that list of tabs
00:18:18.520
when it's
00:18:19.600
called something like this thanks
00:18:22.120
co-pilot that's great
00:18:24.720
um
00:18:26.760
so now when we hit the tab component
00:18:30.000
we're actually just going to push into
00:18:31.440
this list we're going to create a new
00:18:33.440
tab each time and so this list is going
00:18:36.520
to be filled with tabs but we're
00:18:39.080
yielding at the wrong Point here right
00:18:41.320
we are yielding in the middle of this
00:18:43.280
thing so this isn't quite right we can
00:18:47.240
include Flex uh deferred
00:18:50.760
render if you can think of a better name
00:18:52.799
for this you let me know uh and then we
00:18:55.520
don't want to
00:18:57.200
yield instead we are going to iterate
00:19:00.760
over our tabs I can do tabs. each uh and
00:19:05.600
I can do yeah let's do a
00:19:08.520
button uh and let's do tabs. each
00:19:13.679
again and this time we'll do the tab
00:19:17.720
content now copilot's got this slightly
00:19:20.559
wrong
00:19:22.320
uh tab content is a block so we're
00:19:24.799
actually just going to pass it straight
00:19:27.280
in here
00:19:29.280
so now we have two buttons rendered
00:19:32.679
first and then we have two sets of tab
00:19:35.400
content and our
00:19:37.919
interface hasn't even changed we're
00:19:40.799
using exactly the same interface the
00:19:42.799
difference is the block is yielded early
00:19:44.919
and this is more strict component so if
00:19:47.480
we do something here this will not be
00:19:49.799
rendered this is like a void context
00:19:53.400
now so I have one more example if there
00:19:56.000
is
00:19:57.320
time um and that is table I'm just going
00:20:00.480
to jump over to uh my examples MD and
00:20:04.200
I'm going to copy this
00:20:13.400
one
00:20:15.559
okay so I've updated our example it now
00:20:19.760
has um this list of people which I'm
00:20:22.919
just setting in the initializer here but
00:20:24.559
obviously this would come from a
00:20:26.080
controller um and then we're going out
00:20:28.720
to this table component we hand the
00:20:31.320
table component um the people and then
00:20:34.320
it yields uh itself and then we call
00:20:38.200
column and we give it a header and a
00:20:42.200
block to calculate the body from a
00:20:45.280
single record of a
00:20:47.880
person so we can just add t. column
00:20:51.919
email and immediately our whole table is
00:20:55.559
rendered um with the names and emails
00:20:59.600
so doing this in something else would be
00:21:03.960
quite tricky you'd have to um everywhere
00:21:07.159
you use the table you'd have to iterate
00:21:09.200
over um all the headers first for all
00:21:11.919
the columns and then you would have to
00:21:13.720
iterate over all of the body text and
00:21:17.840
you'd have to try to keep those in
00:21:19.600
sync whereas given that this is just in
00:21:23.559
um in our table
00:21:25.480
component we can iterate over those
00:21:27.919
columns once here and we can iterate
00:21:30.400
over the rows and within that iterate
00:21:32.279
over the columns again this time calling
00:21:34.640
the content with our
00:21:38.039
row another thing you can do in flex and
00:21:40.240
this isn't a great example of this um
00:21:42.679
but anywhere that you
00:21:44.760
see uh something that you want to
00:21:47.320
summarize like this piece of text this
00:21:51.000
piece of code really all I want to do
00:21:53.880
when I'm looking at it from here is just
00:21:55.360
see that it is the head right so I'm
00:21:58.679
going to delete it and I'm going to say
00:22:01.799
render head or let's call it
00:22:04.840
header um and then I can just create a
00:22:07.480
private
00:22:12.120
method I'll paste it in
00:22:15.480
here and it still works it's just Ruby
00:22:19.039
so all of the normal refactoring that
00:22:20.600
you would do with Ruby works just fine
00:22:24.559
um you can imagine really big views
00:22:28.080
could just be a nice table of contents
00:22:30.400
at the top and then you can use your
00:22:31.919
symbol navigation to jump to the
00:22:33.320
relevant parts and it just becomes
00:22:35.840
really easy another thing you can do
00:22:38.400
it's a bit cheeky um though there are
00:22:41.120
there are ways you can do it that are
00:22:42.039
less cheeky is let's say I want to wrap
00:22:44.440
this
00:22:45.320
TD um I can actually just Define
00:22:48.159
TD um and I can call div and then
00:22:56.120
Super I don't know why you'd wrap a TD
00:22:58.320
but we get to put a div outside of the
00:23:00.840
super and in fact we can we can do
00:23:02.520
something inside it as well
00:23:06.720
um yeah so um what you probably want to
00:23:10.919
do actually is have a different method
00:23:12.440
that calls a TD in here and then use
00:23:14.720
that method here and that would allow
00:23:16.440
you to inherit from the table and then
00:23:18.919
layer on some extra like functionality
00:23:22.039
so you could customize how TDS are
00:23:24.640
rendered out adding a class or something
00:23:26.760
like that
00:23:29.080
uh so that is the end of the demo I'm
00:23:32.080
going to switch back to my
00:23:35.039
presentation
00:23:39.720
and I have to stop
00:23:43.480
mirroring see if we can get back into
00:23:47.000
this so building views in Ruby allows
00:23:49.799
you to create simple abstractions
00:23:52.080
avoiding duplication and
00:23:55.080
inconsistencies they fully encapsulate
00:23:57.279
specific responsibilities in the view
00:23:58.679
layer you can yield a flexible interface
00:24:01.200
with in order or out of order slots
00:24:03.919
component kits make components more
00:24:05.240
portable easier to use and share with
00:24:07.279
others plus you can install existing
00:24:09.279
kits in your own app you can use one
00:24:11.919
language instead of three Erb HTML Ruby
00:24:15.159
and compared to view components one file
00:24:17.039
instead of two heck you could put
00:24:19.080
multiple components in the same file
00:24:20.679
because they're just constants and
00:24:22.840
finally it's
00:24:26.360
fun if you try it you might like
00:24:30.360
it what's
00:24:33.200
next I'd really like to build a language
00:24:35.440
server that would allow us to offer
00:24:37.200
things like autocomplete for HTML
00:24:38.640
elements and attributes go to definition
00:24:40.679
for components and optional Tailwind
00:24:42.919
autocomplete even when using conditional
00:24:45.080
CSS classes additionally Source Maps
00:24:48.240
would allow us to build Dev tools that
00:24:49.679
allow you to inspect components in the
00:24:52.200
browser and just like jump straight to
00:24:54.240
definition in your code editor by
00:24:55.559
clicking on a component in your browser
00:24:58.520
Flex JS and mor Flex similar to Turbo
00:25:01.080
Flex JS um which we're working on will
00:25:03.720
take advantage of flex unique capability
00:25:05.880
of selectively rendering on the server
00:25:09.039
morflex is a Dom morphing Library uh
00:25:11.279
that we wrote to support FX JS um its
00:25:14.960
algorithm is top to bottom like Flex JS
00:25:17.279
sorry like Flex which means we should be
00:25:19.039
able to support streaming
00:25:21.640
doring form uh forms are the trickiest
00:25:25.360
components to build in rails in my
00:25:26.960
experience I would really like to share
00:25:29.240
some generic abstractions uh to help
00:25:31.760
with this uh so that's something I'll be
00:25:34.279
working on soon and finally first party
00:25:37.600
component kit uh we've got Flex UI
00:25:40.360
protos and zest UI uh I have finally
00:25:44.039
decided that I'm actually going to build
00:25:45.520
a first party component kit I'm not sure
00:25:47.679
what it's going to be called um but the
00:25:52.399
uh the um who was it the the laravel
00:25:57.360
people who made a component kit called
00:26:00.120
flux um spell with an F so maybe maybe
00:26:03.279
that will be some
00:26:05.080
inspiration uh if you want to find out
00:26:07.080
more information there's a link here um
00:26:09.679
to the beta website um Flex 2 is
00:26:13.480
releasing probably today uh as a beta
00:26:17.360
and um there's also a link from there at
00:26:20.200
the top right hand corner to the naming
00:26:22.440
things Discord
00:26:24.440
Channel thank you