Beautiful Animated Nav Bar with React & Framer Motion

Tom Is Loading
28 May 202411:38

Summary

TLDRIn this video, the creator explores the interactive and animated elements of cal.com's landing page, focusing on recreating a navigation bar with a dynamic 'pill' that follows the cursor. Using React and Framer Motion, the tutorial guides viewers through building the animated pill effect, utilizing Tailwind CSS for styling. The process involves setting up state for animating width and position, using refs to determine element dimensions and offsets, and handling hover states for a seamless user experience.

Takeaways

  • 🔗 The video discusses creating a navigation bar with an animated pill effect using React and Framer Motion.
  • 🎨 The pill effect follows the cursor and changes the text color based on its position, using a 'mixed blend mode' of 'difference'.
  • 💻 The tutorial starts with a basic layout using Tailwind CSS, emphasizing that other styling methods can be used.
  • 📐 The navigation bar is structured with an unordered list, positioned relatively to allow absolute positioning of the pill.
  • 🖌 The pill is styled with a 'pointer' cursor, padding, and text transformations to match the design requirements.
  • 🌐 The use of 'z-index' ensures the pill sits behind the text for the desired visual effect.
  • 📊 The 'getBoundingClientRect' method is used to dynamically set the width of the pill based on the hovered element.
  • 🔄 Framer Motion's 'motion' component is utilized to animate the pill's width, opacity, and position.
  • 🔄 The 'useState' hook is employed to manage the pill's animation states, such as width, opacity, and left offset.
  • 🔍 The tutorial suggests using 'useRef' to get the dimensions and position of the hovered tab for accurate animation.
  • 🔙 An 'onMouseLeave' event is implemented to reset the pill's opacity, ensuring it disappears when the cursor leaves the navigation bar.

Q & A

  • What is the main focus of the video?

    -The main focus of the video is to demonstrate how to recreate a cool animated navigation bar with a following cursor effect using React and Framer Motion.

  • What is the 'animated pill' mentioned in the video?

    -The 'animated pill' refers to a small, pill-shaped element that follows the cursor around when hovering over different sections of the navigation bar.

  • Why is the 'tactile almost paper-like feel' of Cal.com highlighted in the video?

    -The 'tactile almost paper-like feel' is highlighted because the video creator appreciates the unique and engaging brand experience that Cal.com has built into their design, and wants to emulate similar interactions.

  • What role does Tailwind CSS play in the video?

    -Tailwind CSS is used for styling the layout in the video. It's noted that even if viewers are not using Tailwind CSS, they can apply the same styling concepts using other methods.

  • What is the purpose of setting the position of the unordered list to 'relative'?

    -Setting the position of the unordered list to 'relative' is necessary because it allows for the absolute positioning of the cursor element relative to the list, which is required for the animation effect.

  • How does the 'mixed blend mode' with the value 'difference' affect the text color?

    -The 'mixed blend mode' with the value 'difference' is used to create an effect where the text color changes based on the background color behind it. If the text is white on a white background, it turns black, and vice versa for a black background.

  • What is the significance of the 'cursor' component in the video?

    -The 'cursor' component is significant because it represents the animated pill that moves and changes width based on the user's cursor position over the navigation tabs.

  • How is the width of the animated pill determined in the video?

    -The width of the animated pill is determined dynamically based on the width of the tab element that the cursor is hovering over.

  • What is the purpose of using Framer Motion in the video?

    -Framer Motion is used to animate the position, width, and opacity of the cursor element smoothly as the user interacts with the navigation bar.

  • How does the video handle the cursor animation when the mouse is not hovering over any tab?

    -When the mouse is not hovering over any tab, the video handles the cursor animation by setting the opacity back to zero using an 'onMouseLeave' event, effectively hiding the cursor.

  • What additional insights does the video offer for extending the functionality?

    -The video suggests that one could extend the functionality by adding scale, different colors, rotation, or turning it into a full navigation with links.

Outlines

00:00

🛠️ Building a Dynamic Navigation Bar

The speaker begins by expressing admiration for the cal.com landing page's tactile, paper-like feel and its cool interactions and animations. They decide to recreate the animated pill effect found in the navigation bar using React and Framer Motion. The process starts with setting up a basic layout using Tailwind CSS, creating a centered component with a background color. A main slide tabs component is then built, consisting of an unordered list of tabs with relative positioning to allow for absolute positioning of a cursor element. The tabs are styled with rounded borders, a white background, and padding. The text is set to uppercase and changes size based on the screen size. The most interesting part is the text color, which uses a mixed blend mode to change colors based on the background. A cursor component is then created, styled to move freely and sit behind the tabs, initially set with a black background. The speaker then introduces the idea of animating the cursor width based on the hovered tab.

05:02

🎨 Animating the Cursor with Framer Motion

The speaker continues by setting up state to animate the cursor's opacity, width, and left position based on the hovered tab. They explain how to use Framer Motion's motion component to animate these properties. The animate prop is used to smoothly transition between different styles. The speaker then demonstrates how to use React's useRef hook to get the dimensions and position of the hovered tab. They show how to get the width of the tab using the getBoundingClientRect method and how to use the offsetLeft property to determine the left position. The speaker sets up an onMouseEnter event to update the state with these values, animating the cursor width and opacity. They also ensure that the cursor follows the mouse across different tabs without any distortion.

10:03

🔚 Cleanup and Further Exploration

The speaker concludes by addressing the issue of the cursor remaining visible after the mouse leaves the tabs. They add an onMouseLeave event to reset the opacity to zero, making the cursor disappear when not hovering over any tab. They suggest various ways to extend the functionality, such as adding scale, color changes, or rotation, and encourage viewers to explore these possibilities. They also recommend a video by Sam Sakov for an alternate approach using Framer Motion's layout animations. The speaker provides a link to the code for this tutorial on their website, available in both JavaScript and TypeScript, and invites viewers to check out other components as well. They end the video by asking for likes and subscriptions and sign off with a friendly farewell.

Mindmap

Keywords

💡cal.com

cal.com is mentioned as a platform that the speaker admires for its brand and interactions. It's used as an example throughout the video to demonstrate how to create a specific navigation bar effect. The admiration for cal.com's tactile, paper-like feel indicates the speaker's focus on user experience and design.

💡Landing Page

A landing page is the entry point for a website where visitors arrive after clicking on a link, often from an email, search engine, or advertisement. In the context of the video, the speaker is interested in breaking down the cool interactions and animations on cal.com's landing page to understand and recreate them.

💡React

React is a popular JavaScript library for building user interfaces, particularly single-page applications. It's used in the video to recreate the navigation bar effect. React's component-based architecture allows for the creation of reusable UI components, which is evident in the speaker's approach to building the navigation bar.

💡Framer Motion

Framer Motion is a library used for creating animated and interactive UI components in React applications. It's mentioned as a tool to help with animating the 'pill' that follows the cursor in the navigation bar. Framer Motion's ability to handle animations smoothly is key to achieving the desired effect.

💡Tailwind CSS

Tailwind CSS is a utility-first CSS framework that provides a set of pre-styled classes to quickly build custom designs. In the video, it's used for styling the basic layout of the navigation bar. Tailwind CSS's utility classes make it easy to apply styles without writing custom CSS, which simplifies the styling process.

💡Navigation Bar

A navigation bar is a UI component that provides navigation links to different parts of a website. In the video, the speaker focuses on creating an animated navigation bar with a 'pill' that follows the cursor. This interactive element is meant to enhance the user experience by providing visual feedback as users hover over different sections.

💡Animated Pill

The 'animated pill' refers to a design element in the navigation bar that moves and changes size based on user interaction. It's used to visually indicate which section of the navigation bar the user's cursor is over. This effect adds a dynamic and engaging interaction to the UI, making it more user-friendly and visually appealing.

💡Cursor

In the context of the video, the 'cursor' refers to the small black pill that moves and animates in response to the user's mouse cursor. It's used as a visual indicator within the navigation bar, showing which tab is currently active or hovered over. The cursor's animation is a key part of the interactive effect being demonstrated.

💡Refs

Refs in React are a way to access DOM nodes or React elements created in the render method. In the video, refs are used to get the width and position of the list items in the navigation bar, which is necessary for animating the cursor (animated pill) to match the hovered tab. This demonstrates a practical use of refs for DOM manipulation within a React component.

💡Animation

Animation in UI design refers to the movement or change in appearance of elements over time. In the video, the speaker recreates an animated effect where a 'pill' follows the cursor and changes size as it moves over different tabs in the navigation bar. Animation is used to enhance user experience by providing visual feedback and making the interface more engaging.

Highlights

The speaker praises cal.com for its tactile, paper-like feel in their brand.

The speaker plans to break down the cool interactions and animations on cal.com's landing page.

A navigation bar with an animated pill that follows the cursor is discussed.

React and Framer Motion are used to recreate the animated pill effect.

The use of Tailwind CSS for styling is mentioned, with assurance that styling will be covered.

A wrapping component is used to center content on the screen with a background color.

An unordered list is used to render tabs with relative positioning for an absolutely positioned cursor.

The tabs have a black border, white background, and padding for styling.

Text is set to uppercase and padding and text size adjust on medium screens.

A mixed blend mode is used to change text color based on the background.

A cursor component is introduced to create the animated pill background.

The cursor has an absolute position and a z-index lower than the tabs.

The cursor's width is animated based on the hovered tab.

State is used to animate the opacity, width, and left position of the cursor.

Framer Motion's motion component is used to animate the list item.

The animate prop in Framer Motion handles the animation between styles.

Refs are used to get the width and left offset of the hovered element.

The getBoundingClientRect function is used to obtain the size of the hovered element.

The left value of the cursor is set based on the offset left of the hovered element.

An onMouseLeave event is added to hide the cursor when the mouse is not hovering.

The speaker suggests extending the project by adding scale, color, or rotation.

An alternate method using Framer Motion for layout animations is recommended.

The code for the project will be available on the speaker's website in JavaScript and TypeScript.

Transcripts

play00:00

if you've watched many of my videos

play00:01

you'll have heard me use cal.com for a

play00:03

number of different examples for a cool

play00:05

landing page a Cool brand and a lot of

play00:07

cool interactions and animations I just

play00:09

love this kind of like tactile almost

play00:11

paper-like feel that they've been able

play00:12

to build into their brand and for a

play00:14

while now I've been wanting to start

play00:15

breaking down some of the cool

play00:17

interactions and animations they built

play00:18

onto their landing page I figured a good

play00:20

start would be something like this

play00:21

navigation bar up here at the top it has

play00:23

this cool animated pill that actually

play00:25

follows your cursor around whenever you

play00:27

Mouse over different sections and we can

play00:28

recreate this effect Rel ly easily using

play00:30

react and framer motion enough talking

play00:32

about it let's go ahead and jump into

play00:34

some code taking a look at my code I've

play00:36

already got some basic layout Happening

play00:38

Here with styling using Tailwind CSS if

play00:40

you're not using Tailwind CSS not a big

play00:42

deal feel free to use whatever you want

play00:43

we'll make sure that we actually go over

play00:45

all of the styling that's going on here

play00:47

so I've got a wrapping component right

play00:48

here this could just well be your screen

play00:50

like your page and for this I'm just

play00:52

taking everything putting it in the

play00:53

middle of the screen and giving it some

play00:55

background color so nothing crazy going

play00:57

on here for our main slide tabs

play00:59

component right here I just have an

play01:01

unordered list which is rendering a

play01:02

number of list items that's these tabs

play01:05

right here obviously for your example

play01:06

you could use anchor tags or whatever it

play01:08

may be but for this example I'm just

play01:09

going to use a basic unordered list this

play01:11

unordered list has a position of

play01:13

relative we need this because here in a

play01:15

second we're going to absolutely

play01:16

position a little cursor that's going to

play01:17

be like that little black pill

play01:19

background and that is going to need to

play01:20

know that it needs to be relative to

play01:22

this unordered list I've added a margin

play01:24

X of Auto again this is really just for

play01:26

this example to put everything in the

play01:27

middle of the screen display a flex just

play01:29

so that all of these tabs sit next to

play01:30

each other rounded full just to round

play01:31

out the borders a two pixel black border

play01:34

background of white and a padding of

play01:36

four pixels for each of my individual

play01:38

tabs it's a little bit more interesting

play01:40

stuff going on so position of relative

play01:42

with a zindex of 10 so that the text

play01:44

sits on top of that little pill that's

play01:46

going to be in the background here in a

play01:47

second display a block a cursor of

play01:49

pointer since this isn't an anchor tag

play01:50

or something some padding on the x-axis

play01:53

of 12 pixels and on the Y AIS of six

play01:55

pixels text of extra small to start and

play01:58

then on medium screen so above 768

play02:02

pixels I'm just bumping those values up

play02:03

so on the x axis my padding is 20 pixels

play02:06

y AIS it is 12 pixels and then also the

play02:09

text goes up to 16 pixels I'm turning

play02:11

all of the text to uppercase no matter

play02:13

what's passed in and then the most

play02:15

interesting part of what's Happening

play02:16

Here is these two Styles right here so

play02:18

you'll notice that I'm setting the text

play02:20

color to white but the text still looks

play02:22

black which is kind of weird right well

play02:24

the reason that that's happening is

play02:25

because we have this mixed blend mode

play02:27

set to difference and essentially what

play02:29

this is going to do is it's going to

play02:30

take the difference of the text color

play02:32

with whatever is behind it so in this

play02:34

case it's just the white background of

play02:35

the Navar itself and it's going to kind

play02:37

of make that the color of the text so if

play02:39

you have white text sitting on top of a

play02:41

white background it's going to turn it

play02:43

black but what's cool is it's actually

play02:44

going to do the opposite of that as well

play02:46

so if our little background pill thing

play02:48

is black it's going to turn the text

play02:50

white and that's going to look really

play02:51

cool because if we have our cursor thing

play02:52

in the background and it's overlapping

play02:54

any of our text just the part that's

play02:56

actually overlapping is going to change

play02:58

colors that might sound a little bit bit

play03:00

confusing but let's go ahead and jump to

play03:01

the cursor part and we'll see that kind

play03:03

of come together so down here below my

play03:04

tab I'm just going to make one more new

play03:06

component called cursor and for now this

play03:08

can just return a list item like this

play03:11

cursor is going to be rendered directly

play03:12

under our tabs like this and I'm just

play03:15

going to drop the Styles in for this as

play03:16

well and we can go ahead and explain

play03:18

them so I've added a position of

play03:19

absolute because this needs to be able

play03:21

to move freely about the background of

play03:23

our navigation bar a zindex of zero

play03:26

because we need this to sit behind our

play03:28

tabs which have a z index of 10 on

play03:30

smaller screens I've given this a height

play03:31

of 28 pixels which this is just mapping

play03:34

directly to what I know the height to be

play03:35

for our list items you could also base

play03:37

the height for these based on the top

play03:39

and bottom absolute positions that's

play03:40

just not how I happened to do it for

play03:42

this example we'll notice also that on

play03:43

medium screens I've bumped that up a

play03:45

little bit then finally I've just given

play03:46

this a rounded full to make it all a

play03:48

rounded Edge as well as a background of

play03:50

black now we're going to notice if I

play03:52

save this that we don't actually see

play03:53

anything yet that's just because we

play03:54

don't have any height set up yet or

play03:56

width rather so we can fix that let's

play03:57

just say width is equal to I don't know

play03:59

say 36 and there we go now we can kind

play04:02

of see what I was talking about here so

play04:03

you'll notice that any of the text that

play04:05

is overlapping the black pill background

play04:07

turns white but anything that is not

play04:09

overlapping stays black so if we have a

play04:11

situation like this where the pill is

play04:13

just halfway overlapping some text only

play04:15

the half that is actually overlapping

play04:16

turns the opposite color now I don't

play04:18

actually want to control the width based

play04:20

on a straight value like this I want to

play04:22

animate it based on whichever one of

play04:24

these pills we're currently hovering

play04:25

over so to see how that can start to

play04:26

come together I'm going to remove our

play04:28

width right here and we'll scroll back

play04:29

up up to our slide tabs and I'm going to

play04:32

create a piece of state which I am going

play04:33

to call position so remembering to

play04:35

import U State that's going to look

play04:37

something like this I have three

play04:38

different values that I actually want to

play04:40

animate at any given point so I want to

play04:42

animate the opacity I want this to not

play04:43

be visible whenever we're not hovering

play04:45

over something I want the width to be

play04:47

dynamic based on whichever one of these

play04:48

items we're hovering over and I want

play04:50

left so this left of zero here to be

play04:52

based also on the left side of whichever

play04:54

one of these tabs we're hovering over we

play04:56

can set these to some random value to

play04:58

start so you can kind of see what's

play04:59

going on on so we'll say left of 60

play05:02

maybe width of 150 and then an opacity

play05:04

of one and go ahead and pass these into

play05:06

our cursor like this now coming down to

play05:09

my cursor component can open this up and

play05:11

before I actually pass in these Styles I

play05:13

want to turn this into a motion list

play05:15

item so that we can animate this value

play05:17

later so if you're not familiar with

play05:19

this just remember to install frame or

play05:20

motion and from frame or motion you can

play05:23

import the motion component so that will

play05:25

look something like this what motion is

play05:28

going to allow us to do is prepend any

play05:30

of our just normal jsx elements so in

play05:32

this case this list item right here and

play05:34

turn it into a motion. li what this

play05:37

unlocks for us is a whole bunch of

play05:39

different things but for our specific

play05:41

example what this mainly does for us is

play05:43

gives us access to a prop called animate

play05:45

and this animate prop can just be passed

play05:47

in any set of styles and it will handle

play05:49

automatically animating between those

play05:51

different sets of styles for you so

play05:53

notice that this position value that

play05:54

we're passing in already directly maps

play05:56

to three different CSS Styles so all

play05:59

that we need to do is take our position

play06:01

and pass it into animate like this if we

play06:03

save that now we should see this

play06:05

starting to come together so we have our

play06:06

pill in the background it's slightly

play06:08

overlapping home so that turns white

play06:10

it's fully overlapping pricing so that

play06:11

turns white and now we can just change

play06:13

these values as we hover over different

play06:15

ones of our tabs and it will

play06:16

automatically handle animating between

play06:18

them for us to do this let's start by

play06:20

zeroing our values back out so we'll say

play06:22

left of zero width of zero and opacity

play06:25

of zero and then we'll take our set

play06:27

position function and pass that into

play06:29

each of of our tabs so that will look

play06:31

something like this just pass set

play06:33

position in and then down on our tab

play06:35

component we can destructure that and

play06:37

start animating this value now remember

play06:39

from our position that there are two

play06:40

specific values that we need we need

play06:42

both the width of the actual element

play06:45

that we are currently hovering over as

play06:47

well as the offset of the left side of

play06:49

the element based on the relative

play06:51

position of the parent so that's kind of

play06:53

confusing but for example if we were

play06:54

hovering over home right here the left

play06:56

offset is essentially going to be zero

play06:58

right plus maybe a little bit of padding

play07:00

so we're going to need that offset

play07:01

between the left side of this container

play07:03

and the tab if we were hovering over

play07:05

pricing it's going to be whatever you

play07:06

know 100 pixels or something like that

play07:08

from right about here over to the left

play07:10

side etc etc as you go down the line to

play07:13

get that value I am going to use refs so

play07:15

what we're going to need to do to get

play07:17

that value is store a ref of the list

play07:19

item and then whenever we Mouse over our

play07:21

list item we can pull those values

play07:23

directly off of that ref so just using a

play07:25

normal react use ref I'll say ref is

play07:28

equal to use ref

play07:30

import that from react and we can

play07:31

default this to null directly on our

play07:34

list item I will say ref is equal to ref

play07:36

like this and the event that we want

play07:38

this to fire on is on Mouse enter like

play07:42

this so just create an inline function

play07:44

like this and that should be fine if

play07:45

you're using typescript to make

play07:46

typescript happy you're going to need to

play07:48

do something like this so I'll say if

play07:50

not ref. current ref. current actually

play07:52

stores the current value of the

play07:54

reference then we're going to want to

play07:56

return and now we can start getting some

play07:57

of our values first off let's actually

play07:59

see how we can get our width of the

play08:01

element that's currently being hovered

play08:02

over now on any reference to an HTML

play08:04

element we're going to have a function

play08:05

called get bounding client wck and

play08:07

that's going to give us a whole bunch of

play08:09

different numbers for the size of our

play08:11

element so to see what I mean let's say

play08:13

const data is equal to ref.

play08:17

current. getet bounding client wrecked

play08:21

and sorry my dogs are barking to see

play08:23

what this actually gives us let's just

play08:24

add a console.log and log out our data

play08:27

I'll hover over one of my pills here

play08:29

let's say pricing and open this up and

play08:31

we'll see all the different fun stuff

play08:32

that this gives us so it gives us things

play08:34

like the height and the width of our

play08:36

element this is specifically what we

play08:37

need but it also gives us the position

play08:39

of the element on the screen

play08:41

unfortunately this is not the position

play08:42

relative to the edge of the container

play08:44

which is what we need we're going to

play08:45

have a different way that we're actually

play08:46

going to get that value so since all

play08:48

that we need is actually width from this

play08:50

piece of data I'm going to remove data

play08:51

and just destructure our value width and

play08:54

down here we can start animating that

play08:55

value so I'll say set position and we

play08:57

can pass in our width now we we also

play08:59

know that we're going to want to

play09:00

increase the opacity on Hover so we can

play09:02

set our opacity to one and this is now

play09:05

going to cover two of our three Styles

play09:08

both our width and our opacity but we

play09:09

still need to figure out how to get our

play09:11

left value let's start by just setting

play09:12

our left to zero so we can see that the

play09:15

width part works if I now hover over

play09:17

home we'll see that that kind of looks

play09:18

about right pricing it increases in size

play09:21

and this little pill is going to keep

play09:22

expanding to the size of whatever we're

play09:24

hovering over but to get our left value

play09:26

we're going to need to do something a

play09:27

little bit different so over here on

play09:29

left I'm going to remove my zero and

play09:30

there's a value directly on our ref

play09:33

called offset left so it's going to look

play09:35

something like ref. current. offset left

play09:39

now you definitely need to make sure

play09:41

that this outer wrapping UL right here

play09:43

is relative because offset left is just

play09:45

going to look at whatever the closest

play09:47

relative parent is and that's how you're

play09:48

going to get your value so setting this

play09:50

to left now we should see this starting

play09:52

to come together hovering over home and

play09:54

then pricing and then features it will

play09:55

now follow me around no matter where I

play09:57

hover so if I go even off of my element

play09:59

go all the way over to blog and there's

play10:00

no Distortion or anything weird going on

play10:02

whenever you hover over all of these

play10:04

different elements finally the last

play10:05

thing that we really need though here is

play10:06

we'll notice that whenever we remove our

play10:08

Mouse the element just stays there which

play10:10

probably isn't what we want so just to

play10:11

round this off I'm going to come back up

play10:13

to my unordered list and add one more

play10:15

call to on Mouse leave this is going to

play10:18

call a function like this and really all

play10:20

that I care about is setting the opacity

play10:22

back to zero so I'll say set position

play10:25

this can take whatever the previous

play10:27

value is and just spread that value in

play10:29

only overriding the opacity setting that

play10:32

back to zero with all of this done now

play10:33

hovering over all of my elements

play10:35

continues to work but as soon as I move

play10:36

my mouse off of the element it goes away

play10:38

if I move it back over here it'll

play10:40

animate from there no matter where I

play10:42

kind of go and add and remove my mouse

play10:43

it just keeps following me around now

play10:45

there's a bunch of different ways that

play10:46

you could extend this you could add

play10:47

scale to this you could add different

play10:49

colors you could make it rotate you

play10:51

could get all kinds of interesting just

play10:52

based on adding different cool styles to

play10:54

this but I will leave that up to you to

play10:56

play with as well as turning this into a

play10:58

full navigation if you wanted to add

play11:00

things like links I will also say that

play11:01

if you're interested in an alternate way

play11:03

of doing this also with frame or motion

play11:05

using layout animations check out this

play11:07

awesome video by Sam sakov he gets

play11:09

essentially the same effect that I have

play11:11

here but with a significantly different

play11:13

strategy for how he does it so if you're

play11:14

just learning frame motion it could be

play11:15

really cool to check out how he did it

play11:17

and compare that with how I've done it

play11:19

here the code for all of this will be

play11:20

free on my website both in JavaScript as

play11:22

well as in typescript just head to the

play11:24

link in the description and then hit

play11:25

code right here if you want JavaScript

play11:27

or typescript you can toggle between the

play11:28

two of those as well as a bunch of other

play11:30

cool components if you want to check

play11:31

those out anyways that's going to be it

play11:33

for me if you learned anything I would

play11:34

massively appreciate a like and a

play11:36

subscribe until next time peace

Rate This

5.0 / 5 (0 votes)

Связанные теги
ReactFramer MotionAnimationWeb DevelopmentUI DesignInteractiveTutorialCSSJavaScriptUX
Вам нужно краткое изложение на английском?