Perfil
La sección Perfil de los ajustes de un producto de IA. Recorta una foto en un círculo, elige un nombre de usuario que se comprueba mientras escribes, confirma un nuevo correo con un código de 6 dígitos, añade enlaces que reconocen el sitio y mira una tarjeta en vivo de cómo te ven los demás.
ProfileSettings es la página de perfil de un producto como Claude o Cursor, hecha para integrarse en cualquier sección de SettingsShell. Dale el perfil guardado y un onSave, y se encarga del resto: un borrador que solo se guarda cuando tú lo dices, errores de campo desde tus comprobaciones o tu servidor, y la barra de guardado flotante de Settings con ⌘S.
Arriba, una tarjeta muestra cómo ven los demás tu perfil y cambia mientras escribes: foto, nombre, handle, biografía y enlaces. Desactiva Show my profile y la tarjeta se atenúa e indica que solo tú puedes verla. Copy link copia la URL del perfil en el portapapeles.
Elige una foto, o suéltala sobre la fila, y se abre en un diálogo de recorte. Arrastra para moverla, haz zoom con el control deslizante, la rueda o un pellizco en el trackpad, y la foto se recorta a un cuadrado en el navegador antes de llegar a onSave como URL de datos. Los archivos de tipo incorrecto, demasiado grandes o de menos de 128 píxeles se rechazan en la fila con el motivo.
El nombre de usuario se comprueba mientras escribes, sin ralentizar la escritura. Las comprobaciones esperan 350ms tras la última tecla, las obsoletas se cancelan mediante un AbortSignal, y los nombres que ya comprobaste responden al instante. Un nombre ocupado muestra tus sugerencias como correcciones de un toque. Si guardas antes de que termine una comprobación, el guardado la espera.
El correo no forma parte del borrador. Change abre un diálogo de dos pasos: introduce la nueva dirección y luego el código de 6 dígitos enviado a ella, que se comprueba solo cuando entra el último dígito. Un código incorrecto sacude y se borra, Resend se desbloquea tras 30 segundos y la fila se actualiza una vez confirmado el código. Una dirección sin verificar muestra Resend link.
Los enlaces aceptan lo que la gente pegue: github.com/you, una URL completa o una dirección www. Los sitios conocidos obtienen su icono, cualquier otro su primera letra. Al guardar se normalizan a URLs https y los vacíos se descartan. Las direcciones que no son enlaces o repiten otra se marcan una por una.
Añade el registro Pro a components.json
components.json Añade tu token
Crea un token en tu página de cuenta y colócalo en
.env.localcomoHEXTAUI_PRO_TOKEN.Añade el bloque
pnpm dlx shadcn@latest add @hextaui-pro/profile
Conéctalo a tu API
Pasa el perfil guardado y un onSave que devuelva errores de campo o lance un error. checkUsername recibe un AbortSignal, así que las comprobaciones obsoletas se cancelan mientras la gente escribe.
Cambiar y verificar el correo
Añade onRequestEmailCode y onVerifyEmailCode para activar el botón Change. Devuelve un mensaje desde onRequestEmailCode para rechazar una dirección, y false desde onVerifyEmailCode para un código incorrecto.
Anatomía
Las partes que compones, de fuera hacia dentro.
| Parte | Descripción |
|---|---|
ProfileSettings | La sección: tarjeta de vista previa, foto, nombre, cómo te llama el asistente, nombre de usuario, biografía, perfil público, enlaces y correo. |
ProfileCard | La vista previa en vivo del perfil público, con Copy link. Se puede usar por sí sola. |
AvatarCropDialog | Recorta una imagen a un cuadrado con arrastre, zoom y teclado, y devuelve una URL de datos. |
ChangeEmailDialog | El cambio de correo en dos pasos: nueva dirección y luego un código de 6 dígitos. |
useUsernameCheck | Comprobaciones de disponibilidad de un nombre de usuario con debounce, cancelables y en caché. |
ProfileSettings
Úsalo dentro de un SettingsSection.
| Prop | Tipo | Predeterminado |
|---|---|---|
profileLo guardado ahora: { avatar, name, nickname, username, bio, links, public }. Cuando cambia y no hay ediciones, el borrador lo sigue. | ProfileValues | – |
onSaveSe llama con los valores recortados y los enlaces normalizados. Devuelve { field: message } para errores de campo, o lanza un error para mostrar el mensaje en la barra de guardado. | (values) => void | errors | Promise<void | errors> | – |
emailLa dirección de inicio de sesión. | string | – |
emailVerifiedMuestra Verified, o Not verified con Resend link. | boolean | true |
checkUsernameComprueba si un nombre de usuario está libre. Recibe el nombre en minúsculas y un AbortSignal. Sin esto, solo se comprueba el formato. | (username, signal) => Promise<{ available, message?, suggestions? }> | – |
onRequestEmailCodeEnvía un código a una dirección nueva. Devuelve un mensaje para rechazar la dirección. Con onVerifyEmailCode, activa Change. | (email) => Promise<void | string> | – |
onVerifyEmailCodeComprueba el código. Devuelve false para un código incorrecto, o lanza un error para mostrar tu mensaje. | (email, code) => Promise<boolean> | – |
onEmailChangeSe llama una vez confirmada la nueva dirección. | (email) => void | – |
onResendVerificationAñade Resend link mientras la dirección no está verificada. | () => Promise<unknown> | – |
profileUrlLa URL del perfil público, mostrada bajo el nombre de usuario y copiada por Copy link. | (username) => string | https://hexta.app/@username |
assistantNameSe usa en «What should Hexta call you?». | string | "Hexta" |
maxAvatarBytesFoto más grande admitida. | number | 5 MB |
maxLinksCuántos enlaces puede tener un perfil. | number | 5 |
maxBioLongitud de la biografía, con un contador. | number | 160 |
| Prop | Tipo | Predeterminado |
|---|---|---|
profileQué mostrar. | { avatar, name, username, bio, links, public } | – |
urlLa URL del perfil que mostrar y copiar. | string | – |
onCopiedSe llama después de copiar el enlace. | () => void | – |
| Prop | Tipo | Predeterminado |
|---|---|---|
sourceLa imagen que recortar. Abierto mientras esté definida. | { url, width, height } | null | – |
onOpenChangeBorra la fuente al cerrarse. | (open) => void | – |
onApplyObtiene el cuadrado recortado como WebP, o PNG donde WebP no es compatible. | (dataUrl) => void | – |
outputSizeLado más largo de la salida en píxeles. Nunca amplía más allá del recorte. | number | 512 |
maxZoomHasta dónde puedes acercar. | number | 4 |
| Prop | Tipo | Predeterminado |
|---|---|---|
openSi está abierto. | boolean | – |
currentEmailSe muestra en la introducción y se rechaza como nueva dirección. | string | – |
onRequestCodeEnvía el código. Devuelve un mensaje para rechazar. | (email) => Promise<void | string> | – |
onVerifyCodeComprueba el código. | (email, code) => Promise<boolean> | – |
onChangedSe llama después de confirmar el código, antes de que se cierre el diálogo. | (email) => void | – |
resendAfterSegundos antes de que se desbloquee Resend code. | number | 30 |
useUsernameCheck(username, options)
Devuelve { status, result, problem, retry, resolve }. status es idle, invalid, checking, available, taken o error.
| Prop | Tipo | Predeterminado |
|---|---|---|
currentEl nombre de usuario guardado, que nunca se comprueba. | string | – |
checkTu comprobación de disponibilidad. | (username, signal) => Promise<UsernameCheck> | – |
delayMilisegundos de espera tras dejar de escribir. | number | 350 |
| Key | Acción |
|---|---|
| Enter | En el último enlace, añade otro enlace y pasa a él. |
| ←→↑↓ | En el diálogo de recorte, mueve la foto. Shift mueve más lejos. |
| +− | En el diálogo de recorte, acerca y aleja. 0 restablece. |
| ⌘S | Guarda mientras haya cambios sin guardar. Ctrl+S en Windows y Linux. |
| Esc | Cierra un diálogo y devuelve el foco al botón que lo abrió. |
- Cada campo se nombra con su fila, y los botones que repiten una palabra dicen sobre qué actúan: Upload photo, Change email, Remove link 2, github.com/you.
- Los resultados del nombre de usuario, los enlaces copiados, los cambios de foto, los enlaces eliminados y un correo modificado se anuncian de forma polite. La comprobación en sí no se anuncia, para que escribir siga en silencio.
- Los errores de campo marcan solo el campo con el fallo, y el foco pasa al primero cuando se rechaza un guardado. El código del correo anuncia comprobando, confirmado e incorrecto.
- Al quitar un enlace, el foco pasa al siguiente enlace, o a Add link cuando no queda ninguno. Al quitar la foto, el foco pasa a Upload.
- El área de recorte es enfocable y funciona con las teclas de flecha y más y menos, y el control deslizante de zoom indica su valor como porcentaje.
- En pantallas táctiles, los inputs usan texto de 16px para que iOS no haga zoom, y los botones de icono tienen objetivos de 44px.
Construido con
Los componentes gratuitos de HextaUI con los que está hecho Profile. Cada uno se instala por separado.
Código
6 archivos, añadidos a components/blocks/profile.