feat(design): the field family, the dropdown trigger, native controls, the no-raw-input lint rule (E28 S3c)
- ui/Input, Textarea, InnerInput + fieldClass (A4): the >= 3:1 edge, a 2px accent focus edge, the danger edge for invalid, md/sm/xs/heading rungs, 1rem and 44 on touch - ui/SelectTrigger (A5): SortControl, FilterSelect, the view switcher and the date filter on one trigger, a pill in a toolbar, r8 in a form - ui/NativeControls (A6): Checkbox, CheckRow, Slider, ColorInput - every raw input swept (~100 sites); inputCls retired; local/input-primitive - useReturnFocus: an in-place editor hands the focus back to its trigger on Enter/Escape (the playlist and Plex title renames, the priority number); the Plex playlist rename gains Escape and an accessible name - back to top: a round 48 FAB (owner decision); DESIGN.md A2 and the log
This commit is contained in:
@@ -31,12 +31,12 @@ import LanguageSwitcher from "./LanguageSwitcher";
|
||||
import { Button } from "./ui/Button";
|
||||
import { trapTab, useDialogChrome } from "./ui/dialogFocus";
|
||||
import { anyBlockingLayerAbove, isTopmost, pushLayer, removeLayer } from "../lib/layerStack";
|
||||
import { inputCls } from "./ui/form";
|
||||
import { entryHash, entrySearch } from "../lib/entryUrl";
|
||||
import type { VerifyEntry } from "../lib/useVerifyEntry";
|
||||
import { MODE_URL, type Mode } from "./welcomeMode";
|
||||
import { IconButton } from "./ui/IconButton";
|
||||
import { Pressable } from "./ui/Pressable";
|
||||
import { Input } from "./ui/Input";
|
||||
|
||||
const EMAIL_RE = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
|
||||
const PASSWORD_MIN = 10;
|
||||
@@ -660,18 +660,19 @@ function AuthCard({ verify }: { verify: VerifyEntry }) {
|
||||
<>
|
||||
<form onSubmit={onSubmit} className="flex flex-col gap-3 mt-3">
|
||||
{mode !== "reset" && (
|
||||
<input
|
||||
<Input
|
||||
className="w-full"
|
||||
type="email"
|
||||
autoComplete="email"
|
||||
required
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder={t("welcome.auth.email")}
|
||||
className={inputCls}
|
||||
/>
|
||||
)}
|
||||
{mode !== "forgot" && mode !== "resend" && (
|
||||
<input
|
||||
<Input
|
||||
className="w-full"
|
||||
type="password"
|
||||
autoComplete={mode === "signin" ? "current-password" : "new-password"}
|
||||
required
|
||||
@@ -682,7 +683,6 @@ function AuthCard({ verify }: { verify: VerifyEntry }) {
|
||||
? t("welcome.auth.newPassword", { min: PASSWORD_MIN })
|
||||
: t("welcome.auth.password")
|
||||
}
|
||||
className={inputCls}
|
||||
/>
|
||||
)}
|
||||
{error && (
|
||||
@@ -769,12 +769,12 @@ function AuthCard({ verify }: { verify: VerifyEntry }) {
|
||||
<form onSubmit={onDemo} className="mt-2 flex flex-col gap-2">
|
||||
<p className="text-2xs text-muted">{t("welcome.auth.demoHint")}</p>
|
||||
<div className="flex gap-2">
|
||||
<input
|
||||
<Input
|
||||
className="w-full"
|
||||
type="email"
|
||||
value={demoEmail}
|
||||
onChange={(e) => setDemoEmail(e.target.value)}
|
||||
placeholder={t("welcome.auth.demoEmail")}
|
||||
className={inputCls}
|
||||
/>
|
||||
<Button type="submit" variant="outline" size="lg" disabled={demoBusy}>
|
||||
{demoBusy ? t("welcome.auth.working") : t("welcome.auth.demoEnter")}
|
||||
|
||||
Reference in New Issue
Block a user