forked from storacha/w3up
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: eject @w3ui/react from w3console (storacha#383)
We don't have the bandwidth to support @w3ui/react anymore, so migrate w3console to use the "headless" components directly. Importantly, this means we can use idiomatic TailwindCSS across the board rather than the hybrid raw-CSS/Tailwind approach we had been using. A few years ago I would have considered the CSS changes here a step backwards, moving from semantic classes to Tailwind utility classes sprinkled everywhere. While there may be some opportunities for CSS-class-based abstraction in a few places, Tailwind's docs make the case for being extremely conservative with this type of componentization: https://tailwindcss.com/docs/reusing-styles I have created a `w3ui-button` class, but it probably needs to be pared down - evidence for this can be found in the authenticator's "Register" button in which I needed to copy most of the styles from the `w3ui-button` class to customize it the way I wanted. I also created an `authenticator` class, but it may be a better idea to create a React component for this. I have this configured to merge to `feat/pre-paging` for now to make this PR cleaner, but won't merge it until that hits `main` and this gets automatically retargetted.
- Loading branch information
Showing
18 changed files
with
679 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
packages/w3ui/examples/react/w3console/src/components/Authenticator.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import React from 'react' | ||
import { | ||
Authenticator as AuthCore, | ||
useAuthenticator | ||
} from '@w3ui/react-keyring' | ||
|
||
export function AuthenticationForm (): JSX.Element { | ||
const [{ submitted }] = useAuthenticator() | ||
|
||
return ( | ||
<div className='authenticator'> | ||
<AuthCore.Form className='bg-gradient-to-br from-blue-500 to-cyan-500 rounded-xl shadow-md px-10 pt-14 pb-8'> | ||
<div> | ||
<label className='block mb-2 uppercase text-white/80 text-xs font-semibold tracking-wider m-1 font-mono' htmlFor='authenticator-email'>Email</label> | ||
<AuthCore.EmailInput className='block rounded-md p-2 w-80 bg-white shadow-md' id='authenticator-email' required /> | ||
</div> | ||
<button | ||
className='mt-2 bg-white/0 w-full hover:bg-blue-800 rounded-md w-full text-sm font-medium text-white py-2 px-8 transition-colors ease-in' | ||
type='submit' | ||
disabled={submitted} | ||
> | ||
Register | ||
</button> | ||
</AuthCore.Form> | ||
</div> | ||
) | ||
} | ||
|
||
export function AuthenticationSubmitted (): JSX.Element { | ||
const [{ email }] = useAuthenticator() | ||
|
||
return ( | ||
<div className='authenticator'> | ||
<div className='bg-gray-400 px-24 py-16 rounded-md'> | ||
<h1 className='text-xl'>Verify your email address!</h1> | ||
<p className='pt-2 pb-4'> | ||
Click the link in the email we sent to {email} to sign in. | ||
</p> | ||
<AuthCore.CancelButton className='w3ui-button w-full'> | ||
Cancel | ||
</AuthCore.CancelButton> | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
export function AuthenticationEnsurer ({ | ||
children | ||
}: { | ||
children: JSX.Element | JSX.Element[] | ||
}): JSX.Element { | ||
const [{ spaces, submitted }] = useAuthenticator() | ||
const registered = Boolean(spaces.some((s) => s.registered())) | ||
if (registered) { | ||
return <>{children}</> | ||
} | ||
if (submitted) { | ||
return <AuthenticationSubmitted /> | ||
} | ||
return <AuthenticationForm /> | ||
} | ||
|
||
interface AuthenticatorProps { | ||
children: JSX.Element | JSX.Element[] | ||
className?: string | ||
} | ||
|
||
export function Authenticator ({ | ||
children, | ||
className = '' | ||
}: AuthenticatorProps): JSX.Element { | ||
return ( | ||
<AuthCore as='div' className={className}> | ||
<AuthenticationEnsurer>{children}</AuthenticationEnsurer> | ||
</AuthCore> | ||
) | ||
} | ||
|
||
/** | ||
* Wrapping a component with this HoC ensures an identity exists. | ||
*/ | ||
export function withIdentity<C extends React.JSXElementConstructor<P>, P> ( | ||
Component: C | ||
) { | ||
return (props: any) => ( | ||
<Authenticator> | ||
<Component {...props} /> | ||
</Authenticator> | ||
) | ||
} |
File renamed without changes.
104 changes: 104 additions & 0 deletions
104
packages/w3ui/examples/react/w3console/src/components/SpaceCreator.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import type { ChangeEvent } from 'react' | ||
|
||
import React, { useState } from 'react' | ||
import { useKeyring } from '@w3ui/react-keyring' | ||
import { ArrowPathIcon } from '@heroicons/react/20/solid' | ||
|
||
export function SpaceCreatorCreating (): JSX.Element { | ||
return ( | ||
<div className='flex flex-col items-center space-y-4'> | ||
<h5>Creating Space...</h5> | ||
<ArrowPathIcon className='animate-spin w-6' /> | ||
</div> | ||
) | ||
} | ||
|
||
interface SpaceCreatorProps { | ||
className?: string | ||
} | ||
|
||
export function SpaceCreator ({ | ||
className = '' | ||
}: SpaceCreatorProps): JSX.Element { | ||
const [, { createSpace, registerSpace }] = useKeyring() | ||
const [creating, setCreating] = useState(false) | ||
const [submitted, setSubmitted] = useState(false) | ||
const [email, setEmail] = useState('') | ||
const [name, setName] = useState('') | ||
|
||
function resetForm (): void { | ||
setEmail('') | ||
setName('') | ||
} | ||
|
||
async function onSubmit (e: React.FormEvent<HTMLFormElement>): Promise<void> { | ||
e.preventDefault() | ||
setSubmitted(true) | ||
try { | ||
await createSpace(name) | ||
// ignore this because the Space UI should handle helping the user recover | ||
// from space registration failure | ||
void registerSpace(email) | ||
} catch (error) { | ||
/* eslint-disable no-console */ | ||
console.error(error) | ||
/* eslint-enable no-console */ | ||
throw new Error('failed to register', { cause: error }) | ||
} finally { | ||
resetForm() | ||
setSubmitted(false) | ||
} | ||
} | ||
/* eslint-disable no-nested-ternary */ | ||
return ( | ||
<div className={`${className}`}> | ||
{creating | ||
? ( | ||
submitted | ||
? ( | ||
<SpaceCreatorCreating /> | ||
) | ||
: ( | ||
<form | ||
className='flex flex-col space-y-2' | ||
onSubmit={(e: React.FormEvent<HTMLFormElement>) => { | ||
void onSubmit(e) | ||
}} | ||
> | ||
<input | ||
className='text-black py-1 px-2 rounded' | ||
type='email' | ||
placeholder='Email' | ||
value={email} | ||
onChange={(e: ChangeEvent<HTMLInputElement>) => { | ||
setEmail(e.target.value) | ||
}} | ||
/> | ||
<input | ||
className='text-black py-1 px-2 rounded' | ||
placeholder='Name' | ||
value={name} | ||
onChange={(e: ChangeEvent<HTMLInputElement>) => { | ||
setName(e.target.value) | ||
}} | ||
/> | ||
<input | ||
type='submit' | ||
className='w3ui-button' | ||
value='Create' | ||
/> | ||
</form> | ||
) | ||
) | ||
: ( | ||
<button | ||
className='w3ui-button py-2' | ||
onClick={() => { setCreating(true) }} | ||
> | ||
Add Space | ||
</button> | ||
)} | ||
</div> | ||
) | ||
/* eslint-enable no-nested-ternary */ | ||
} |
Oops, something went wrong.