Block · Account
NewSign In SwiftUI Block
A SwiftUI login screen. The sign-in section of a welcome screen: email and password, Sign in with Apple, a passkey and Create account in one block.
Email and password on one card, checked on submit and then live, with Sign in running your closure through working, done and failed. Forgot password confirms inline, Sign in with Apple is the system button in the colour of the appearance, and a link at the foot switches to Create account with password rules that tick off.
- SwiftUI
- iOS 17.0+
- sign-in
$199 once, every piece included. See how installing works · Sign in
01
What's included
SwiftUI source you own, built on Apple frameworks only.
- Email and password that check on submit, then live, with Password AutoFill
- Sign in shows working, a check, or your error's message
- Forgot password sends a link and confirms "Check your email" inline
- The system Sign in with Apple button, plus an optional passkey
- Create account in the same block, with password rules that tick off
Requires
com.apple.developer.applesignin
02
Implementation notes
How it behaves, what it handles, and the decisions behind it.
One card holds the form. Email and password stay quiet until Sign in is tapped, then show what's wrong under each field in the danger colour and keep checking live as they're corrected; Return moves from field to field and signs in from the password. The password has a reveal eye, and Password AutoFill offers saved logins. Sign in runs your closure: a spinner takes the label's place, a check follows when it returns, and a thrown error's message shows under the button. "Forgot password?" sits on the password's label row; it sends a reset link to the email typed so far and confirms "Check your email" in the card. Under an "or" hairline, Sign in with Apple is the system button, white on dark grounds and black on light ones, with its own progress and check, and "Sign in with a passkey" appears when you pass it. A plain link under the card switches to Create account, which adds a name field and password rules that tick off as they're typed and turn to the danger colour if a submit finds one unmet. A legal line with your links can close the block. Show the block redacted while a session restores and it draws grey shapes in its own layout.
Notes
SignInBlock(mode:email:passwordRules:legal:onSignIn:onCreateAccount:onForgotPassword:onApple:onAppleRequest:onPasskey:onSuccess:). OnlyonSignInis required; every other part appears when you pass it. It is a section: no navigation stack, background, padding or scroll view of its own, so place it in your own column, such as aScrollViewwith.padding(.horizontal, 20), or a sheet.onSignInreceivesSignInBlock.Credentials(the email, trimmed, and the password).onCreateAccountreceivesSignInBlock.NewAccount(name, email, password) once the name is filled, the email reads right and every rule is met. Both areasync throws: return to succeed, throw to fail. The block shows a thrownLocalizedError'serrorDescription, so throw "That email and password don't match." in your own words; anything else shows "Couldn't sign in. Try again." ACancellationErrorgoes back to rest quietly.- After a success the button holds its check for about a second, then calls
onSuccess. Move to your app there, not at the end ofonSignIn, so the check is seen. The block then settles back with the password cleared. modeis aBinding<SignInBlock.Mode>(.signInor.createAccount) for a screen that changes its own title with it. Leave it out and the block keeps the mode, starting on Sign in. WithoutonCreateAccountthe block stays on Sign in and hides the link.emailis aBinding<String>to prefill a returning person's address. The password always stays inside the block.passwordRulesis a list ofSignInBlock.PasswordRule, each atitleand anisMetcheck that sees the wholeNewAccount.PasswordRule.defaultsis.minimumLength(8),.numberOrSymboland.avoidsNameAndEmail. Match them to what your server enforces.onForgotPasswordreceives the trimmed email. If the email is empty or malformed the field says so and takes focus instead. While the closure runs the link shows a spinner; when it returns, "Check your email" and the address appear under the password until the email changes. A thrown error shows under the field.onApplereceives Sign in with Apple'sResult<ASAuthorization, Error>; send theASAuthorizationAppleIDCredential'sidentityTokenandauthorizationCodeto your server. The block asks for the name and email scopes, then callsonAppleRequestso you can set a hashed nonce or change the scopes. Closing Apple's sheet never reaches your closure. A failure Apple reports shows "Couldn't sign in with Apple. Try again." unless your closure throws its own error.onPasskeyruns your passkey sign-in, anASAuthorizationControllerwith anASAuthorizationPlatformPublicKeyCredentialProviderassertion request. ThrowASAuthorizationError.canceledand the button goes back to rest quietly. It shows on Sign in only.legalis anAttributedStringshown under the block with its links underlined.SignInBlock.legalNotice(terms:privacy:)builds "By continuing, you agree to the Terms of Service and Privacy Policy." with your two URLs. Links open with the environment'sopenURL.- Loading: apply
.redacted(reason: .placeholder)while a session restores, and the block draws its card, fields and buttons as grey shapes, breathing unless Reduce Motion is on. - Fields: Email is
.usernamewith the email keyboard, so Password AutoFill pairs it with the password (.passwordon Sign in,.newPasswordon Create account, which offers a strong password). Name is.name. Return reads Next, then Go. - Haptics: success when a sign-in lands, an error when one fails, a warning when a submit is refused, and a selection tick when the mode changes.
- VoiceOver reads each field by its label with its error as a hint, announces refused submits, failures, "Signed in" and the reset confirmation, and reads each password rule with "Done" or "Not yet". The reveal eye reads "Show password" or "Hide password". Every control is at least 44 points tall; the Forgot password link's target reaches into the space around its row. At accessibility sizes the link moves under the Password label, fields grow and messages wrap.
- Reduce Motion turns every change into a short fade.
SignInBlockExampleat the end ofSignInBlock.swiftis Folio's welcome screen from the preview: the app's name, "Welcome back" and a line under it, then the block with every option. It owns the mode, so its title becomes "Create your account" with it, and its stand-in auth refuses a password shorter than eight characters so both outcomes can be tried. It wears the Studio brand unless the host set one.
Theming
- Reads
SPThemefrom@Environment(\.spTheme)and requires thedesign-systemitem. - The card is
color.surfacewithradius.lgand 16 point padding (space.lg); field groups sit 16 points apart, with 24 above the button. - Fields are 52 points tall on
fillwithradius.mdand a 1 pointseparatorhairline that turns totextPrimarywhen focused and todangeron an error. Labels aretype.subheadintextSecondary, inputtype.bodyintextPrimary, promptstextTertiary, errorstype.footnoteindanger. The reveal eye istextSecondary. - Sign in is the only accent:
accentwithaccentOnintype.headline,radius.md, 52 points. Sign in with a passkey usesfillwithtextPrimary. Sign in with Apple takes the same height and corner, black or white by appearance as Apple asks. - Links are
textPrimary(Forgot password intype.subheadmedium, the Create account link intype.subheadsemibold besidetextSecondary). The "or" divider isSPHairlinewithtype.footnoteintextSecondary. Met rules aretextPrimary, unmet onestextSecondarywith atextTertiarycircle. - States move with
motion.snappy, the mode change withmotion.smooth, the buttons' press withmotion.standard.
Requirements
- Sign in with Apple capability, when you pass
onApple. - Associated Domains with a
webcredentials:entry for your domain, for Password AutoFill to offer saved logins and for passkeys.
03
Keep building
Pieces that work well next to this one.