I think the duplicate I proposed should tell you "yes, you're going about this in a reasonable way", but there are a couple points that I think are worth addressing separately.
The 3 salts used in steps 2-4 could be derived from the email by using SHA3-512 and take the necessary length of bytes needed for those functions?
Salts should not be reused, and they should not be predictable. By using a hash of the username, the same salt will be used whenever a user changes their password. It also allows an attacker to trivially predict the salt that will be used and start generating a rainbow table in the hope that a future leak will allow them to make use of it.
In the case of the login key salt, since it has to be used client-side prior to logging in, anyone who knows the username must be able to retrieve the salt from the server anyway, so generating the salt from the username may not be a deal breaker here, however it would still be best to avoid using the same salt when a user changes their password. The encryption key salt should be randomly generated in order to prevent pre-computation of rainbow tables, which means it needs to be stored on the server (unless you're ok with users not being able to change browsers/computers).
If you compare this to a normal app that just sends the password to the server, this isn't really any less secure to outside attackers. For a rainbow table using the login-key salt to be useful, someone would have to obtain the user's login-key, which in other apps would be the password itself.
If the encryption key salt is only sent to authenticated users, then the only rainbow table that could be generated would be for the user's login key. If there is a database leak, then the server-side bcrypt hash of the login key will have a separate random salt that the rainbow table won't be useful for, and the encrypted data will be encrypted using the encryption key salt that the attacker wouldn't have prior access to, so allowing anyone to access the login key salt shouldn't pose too much of a threat.
Of course, if the server itself is malicious, nothing prevents it from trying to crack the password, but this isn't really avoidable.
I was thinking it is important that the server has no information how to decrypt the vault.
While that certainly sounds nice, unless your users take extreme measures (ie auditing the code and verifying it hasn't changed every time they load the page) they'll still have to trust the server to some extent. It's the server that sends them the JavaScript every time they load the page, and it would be easy for someone malicious in control of the server to modify the code to have it send them the encryption keys.
Client-side encryption with a key known only to the user is useful to mitigate the damage done if the server is compromised in the future, but if a user connects to the server while it's compromised/malicious they're probably going to be out of luck.
Thus should never know in any point in time the secret key for the vault. By just using one password for login and encryption sounds not reasonable?
Running the password through bcrypt and then HKDF client-side with separate salts for the encryption key and authentication should be sufficient to solve this problem. Just be aware that, historically, JavaScript hasn't been a good choice for password hashing due to its speed. If a native implementation is 10x faster than a JavaScript implementation, the JavaScript will have to run 10x longer for the same security. A WebAssembly implementation may work better, but benchmarking is recommended.