diff --git a/frontend/index.html b/frontend/index.html
index 6dd149a..52c287f 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -4,12 +4,6 @@
Tranquil PDS
-
-
-
diff --git a/frontend/src/lib/toast.svelte.ts b/frontend/src/lib/toast.svelte.ts
index b077bae..6803039 100644
--- a/frontend/src/lib/toast.svelte.ts
+++ b/frontend/src/lib/toast.svelte.ts
@@ -5,7 +5,6 @@ export interface Toast {
type: ToastType;
message: string;
duration: number;
- dismissing?: boolean;
}
let nextId = 0;
@@ -33,14 +32,7 @@ export function showToast(
}
export function dismissToast(id: number): void {
- const toast = toasts.find((t) => t.id === id);
- if (!toast || toast.dismissing) return;
-
- toasts = toasts.map((t) => t.id === id ? { ...t, dismissing: true } : t);
-
- setTimeout(() => {
- toasts = toasts.filter((t) => t.id !== id);
- }, 150);
+ toasts = toasts.filter((t) => t.id !== id);
}
export function clearAllToasts(): void {
diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json
index ae95b30..21fcd59 100644
--- a/frontend/src/locales/en.json
+++ b/frontend/src/locales/en.json
@@ -266,7 +266,7 @@
"appPasswords": {
"create": "Create",
"name": "Name",
- "namePlaceholder": "App name (eg., Graysky)",
+ "namePlaceholder": "App name (eg. Witchsky)",
"created": "App Password Created",
"createdMessage": "Copy this password now. You won't be able to see it again.",
"noPasswords": "No app passwords yet",
@@ -334,7 +334,7 @@
"adding": "Adding...",
"noPasskeys": "No passkeys registered",
"passkeyName": "Passkey name",
- "passkeyNamePlaceholder": "eg., MacBook Pro, iPhone",
+ "passkeyNamePlaceholder": "eg. yubikey, phone",
"rename": "Rename",
"deletePasskey": "Delete",
"deletePasskeyConfirm": "Delete passkey \"{name}\"? You won't be able to use it to sign in anymore.",
@@ -762,7 +762,7 @@
"externalDidPlaceholder": "did:web:yourdomain.com",
"externalDidHint": "Serve DID document at",
"passkeyName": "Passkey Name",
- "passkeyNamePlaceholder": "MacBook Touch ID",
+ "passkeyNamePlaceholder": "eg. yubikey, phone",
"passkeyNameHint": "Optional identifier",
"setupPasskey": "Create Passkey",
"passkeyDescription": "Register a passkey for this account",
@@ -1038,7 +1038,7 @@
"title": "Set Up Your Passkey",
"desc": "Your email has been verified. Now set up your passkey for secure, passwordless login.",
"nameLabel": "Passkey Name (optional)",
- "namePlaceholder": "eg., MacBook Pro, iPhone",
+ "namePlaceholder": "eg. yubikey, phone",
"nameHint": "A friendly name to identify this passkey",
"instructions": "Click the button below to register your passkey. Your device will prompt you to use biometrics (fingerprint, Face ID) or a security key.",
"register": "Register Passkey",
diff --git a/frontend/src/locales/fi.json b/frontend/src/locales/fi.json
index 20d45fa..0b68cd2 100644
--- a/frontend/src/locales/fi.json
+++ b/frontend/src/locales/fi.json
@@ -278,7 +278,7 @@
"byController": "Hallinnoijan luoma",
"create": "Luo",
"name": "Nimi",
- "namePlaceholder": "Sovelluksen nimi (esim. Graysky)",
+ "namePlaceholder": "Sovelluksen nimi (esim. Witchsky)",
"deleteConfirm": "Peruuta sovelluksen salasana \"{name}\"?",
"deleted": "Sovelluksen salasana peruutettu",
"loadFailed": "Sovellusten salasanojen lataus epäonnistui",
@@ -334,7 +334,7 @@
"adding": "Lisätään...",
"noPasskeys": "Ei rekisteröityjä pääsyavaimia",
"passkeyName": "Pääsyavaimen nimi",
- "passkeyNamePlaceholder": "esim. MacBook Pro, iPhone",
+ "passkeyNamePlaceholder": "esim. yubikey, puhelin",
"rename": "Nimeä uudelleen",
"deletePasskey": "Poista",
"deletePasskeyConfirm": "Poista pääsyavain \"{name}\"? Et voi enää käyttää sitä kirjautumiseen.",
@@ -758,7 +758,7 @@
},
"identityType": "Identiteettityyppi",
"identityTypeHint": "Valitse, miten hajautettua identiteettiäsi hallitaan.",
- "passkeyNamePlaceholder": "esim. MacBook Touch ID",
+ "passkeyNamePlaceholder": "esim. yubikey, puhelin",
"passkeyNameHint": "Ystävällinen nimi tämän pääsyavaimen tunnistamiseksi",
"createPasskey": "Luo pääsyavain",
"didPlcRecommended": "did:plc (Suositeltava)",
@@ -1037,7 +1037,7 @@
"title": "Määritä pääsyavaimesi",
"desc": "Sähköpostisi on vahvistettu. Määritä nyt pääsyavaimesi turvallista, salasanatonta kirjautumista varten.",
"nameLabel": "Pääsyavaimen nimi (valinnainen)",
- "namePlaceholder": "esim. MacBook Pro, iPhone",
+ "namePlaceholder": "esim. yubikey, puhelin",
"nameHint": "Kutsumanimi tämän pääsyavaimen tunnistamiseen",
"instructions": "Klikkaa alla olevaa painiketta rekisteröidäksesi pääsyavaimesi. Laitteesi pyytää käyttämään biometriikkaa (sormenjälki, Face ID) tai suojausavainta.",
"register": "Rekisteröi pääsyavain",
diff --git a/frontend/src/locales/ja.json b/frontend/src/locales/ja.json
index 691302a..8d5754c 100644
--- a/frontend/src/locales/ja.json
+++ b/frontend/src/locales/ja.json
@@ -278,7 +278,7 @@
"byController": "管理者作成",
"create": "作成",
"name": "名前",
- "namePlaceholder": "アプリ名(例:Graysky)",
+ "namePlaceholder": "アプリ名(例:Witchsky)",
"deleteConfirm": "アプリパスワード「{name}」を取り消しますか?",
"deleted": "アプリパスワードを取り消しました",
"loadFailed": "アプリパスワードの読み込みに失敗しました",
@@ -334,7 +334,7 @@
"adding": "追加中...",
"noPasskeys": "登録されたパスキーはありません",
"passkeyName": "パスキー名",
- "passkeyNamePlaceholder": "例: MacBook Pro、iPhone",
+ "passkeyNamePlaceholder": "例: yubikey、スマホ",
"rename": "名前変更",
"deletePasskey": "削除",
"deletePasskeyConfirm": "パスキー「{name}」を削除しますか?サインインに使用できなくなります。",
@@ -758,7 +758,7 @@
},
"identityType": "アイデンティティタイプ",
"identityTypeHint": "分散型アイデンティティの管理方法を選択してください。",
- "passkeyNamePlaceholder": "例:MacBook Touch ID",
+ "passkeyNamePlaceholder": "例: yubikey、スマホ",
"passkeyNameHint": "このパスキーを識別するための名前",
"createPasskey": "パスキーを作成",
"didPlcRecommended": "did:plc(推奨)",
@@ -1037,7 +1037,7 @@
"title": "パスキーを設定",
"desc": "メールが確認されました。安全なパスワードレスログインのためにパスキーを設定してください。",
"nameLabel": "パスキー名(任意)",
- "namePlaceholder": "例:MacBook Pro、iPhone",
+ "namePlaceholder": "例: yubikey、スマホ",
"nameHint": "このパスキーを識別するためのわかりやすい名前",
"instructions": "下のボタンをクリックしてパスキーを登録してください。デバイスが生体認証(指紋、Face ID)またはセキュリティキーの使用を促します。",
"register": "パスキーを登録",
diff --git a/frontend/src/locales/ko.json b/frontend/src/locales/ko.json
index e7d3305..5767992 100644
--- a/frontend/src/locales/ko.json
+++ b/frontend/src/locales/ko.json
@@ -278,7 +278,7 @@
"byController": "컨트롤러 생성",
"create": "생성",
"name": "이름",
- "namePlaceholder": "앱 이름 (예: Graysky)",
+ "namePlaceholder": "앱 이름 (예: Witchsky)",
"deleteConfirm": "앱 비밀번호 \"{name}\"을(를) 취소하시겠습니까?",
"deleted": "앱 비밀번호가 취소되었습니다",
"loadFailed": "앱 비밀번호 로딩 실패",
@@ -334,7 +334,7 @@
"adding": "추가 중...",
"noPasskeys": "등록된 패스키가 없습니다",
"passkeyName": "패스키 이름",
- "passkeyNamePlaceholder": "예: MacBook Pro, iPhone",
+ "passkeyNamePlaceholder": "예: yubikey, 휴대폰",
"rename": "이름 변경",
"deletePasskey": "삭제",
"deletePasskeyConfirm": "패스키 \"{name}\"을(를) 삭제하시겠습니까? 더 이상 로그인에 사용할 수 없습니다.",
@@ -758,7 +758,7 @@
},
"identityType": "아이덴티티 유형",
"identityTypeHint": "분산 아이덴티티 관리 방법을 선택하세요.",
- "passkeyNamePlaceholder": "예: MacBook Touch ID",
+ "passkeyNamePlaceholder": "예: yubikey, 휴대폰",
"passkeyNameHint": "이 패스키를 식별할 수 있는 이름",
"createPasskey": "패스키 생성",
"didPlcRecommended": "did:plc (권장)",
@@ -1037,7 +1037,7 @@
"title": "패스키 설정",
"desc": "이메일이 인증되었습니다. 안전한 비밀번호 없는 로그인을 위해 패스키를 설정하세요.",
"nameLabel": "패스키 이름 (선택사항)",
- "namePlaceholder": "예: MacBook Pro, iPhone",
+ "namePlaceholder": "예: yubikey, 휴대폰",
"nameHint": "이 패스키를 식별하기 위한 이름",
"instructions": "아래 버튼을 클릭하여 패스키를 등록하세요. 기기에서 생체 인식(지문, Face ID) 또는 보안 키 사용을 요청합니다.",
"register": "패스키 등록",
diff --git a/frontend/src/locales/sv.json b/frontend/src/locales/sv.json
index 37f91e4..494d7be 100644
--- a/frontend/src/locales/sv.json
+++ b/frontend/src/locales/sv.json
@@ -278,7 +278,7 @@
"byController": "Av controller",
"create": "Skapa",
"name": "Namn",
- "namePlaceholder": "Appnamn (t.ex. Graysky)",
+ "namePlaceholder": "Appnamn (t.ex. Witchsky)",
"deleteConfirm": "Återkalla applösenord \"{name}\"?",
"deleted": "Applösenord återkallat",
"loadFailed": "Kunde inte ladda applösenord",
@@ -334,7 +334,7 @@
"adding": "Lägger till...",
"noPasskeys": "Inga nycklar registrerade",
"passkeyName": "Nyckelnamn",
- "passkeyNamePlaceholder": "t.ex. MacBook Pro, iPhone",
+ "passkeyNamePlaceholder": "t.ex. yubikey, telefon",
"rename": "Byt namn",
"deletePasskey": "Radera",
"deletePasskeyConfirm": "Radera nyckel \"{name}\"? Du kommer inte att kunna använda den för att logga in längre.",
@@ -758,7 +758,7 @@
},
"identityType": "Identitetstyp",
"identityTypeHint": "Välj hur din decentraliserade identitet ska hanteras.",
- "passkeyNamePlaceholder": "t.ex. MacBook Touch ID",
+ "passkeyNamePlaceholder": "t.ex. yubikey, telefon",
"passkeyNameHint": "Ett vänligt namn för att identifiera denna nyckel",
"createPasskey": "Skapa nyckel",
"didPlcRecommended": "did:plc (Rekommenderas)",
@@ -1037,7 +1037,7 @@
"title": "Konfigurera din passkey",
"desc": "Din e-post har verifierats. Konfigurera nu din passkey för säker, lösenordslös inloggning.",
"nameLabel": "Passkey-namn (valfritt)",
- "namePlaceholder": "t.ex. MacBook Pro, iPhone",
+ "namePlaceholder": "t.ex. yubikey, telefon",
"nameHint": "Ett vänligt namn för att identifiera denna passkey",
"instructions": "Klicka på knappen nedan för att registrera din passkey. Din enhet kommer att uppmana dig att använda biometri (fingeravtryck, Face ID) eller en säkerhetsnyckel.",
"register": "Registrera passkey",
diff --git a/frontend/src/locales/zh.json b/frontend/src/locales/zh.json
index 18f3f06..352b6bc 100644
--- a/frontend/src/locales/zh.json
+++ b/frontend/src/locales/zh.json
@@ -278,7 +278,7 @@
"byController": "由控制者创建",
"create": "创建",
"name": "名称",
- "namePlaceholder": "应用名称(如 Graysky)",
+ "namePlaceholder": "应用名称(如 Witchsky)",
"deleteConfirm": "撤销应用专用密码「{name}」?",
"deleted": "应用专用密码已撤销",
"loadFailed": "加载应用专用密码失败",
@@ -334,7 +334,7 @@
"adding": "添加中...",
"noPasskeys": "未注册通行密钥",
"passkeyName": "通行密钥名称",
- "passkeyNamePlaceholder": "如 MacBook Pro、iPhone",
+ "passkeyNamePlaceholder": "如 yubikey、手机",
"rename": "重命名",
"deletePasskey": "删除",
"deletePasskeyConfirm": "删除通行密钥「{name}」?您将无法再使用它登录。",
@@ -761,7 +761,7 @@
"externalDidPlaceholder": "did:web:yourdomain.com",
"externalDidHint": "您需要在以下地址提供 DID 文档",
"passkeyName": "通行密钥名称",
- "passkeyNamePlaceholder": "MacBook Touch ID",
+ "passkeyNamePlaceholder": "如 yubikey、手机",
"passkeyNameHint": "可选标识",
"createPasskey": "创建通行密钥",
"errors": {
@@ -1037,7 +1037,7 @@
"title": "设置您的通行密钥",
"desc": "您的邮箱已验证。现在设置通行密钥以实现安全的无密码登录。",
"nameLabel": "通行密钥名称(可选)",
- "namePlaceholder": "例如:MacBook Pro、iPhone",
+ "namePlaceholder": "如 yubikey、手机",
"nameHint": "用于识别此通行密钥的友好名称",
"instructions": "点击下方按钮注册您的通行密钥。您的设备将提示您使用生物识别(指纹、面容ID)或安全密钥。",
"register": "注册通行密钥",
diff --git a/frontend/src/main.ts b/frontend/src/main.ts
index 6ef7a3a..99fef30 100644
--- a/frontend/src/main.ts
+++ b/frontend/src/main.ts
@@ -1,4 +1,7 @@
import "./styles/base.css";
+import "./styles/pages.css";
+import "./styles/dashboard.css";
+import "./styles/migration.css";
import App from "./App.svelte";
import { mount } from "svelte";
diff --git a/frontend/src/styles/tokens.css b/frontend/src/styles/tokens.css
index b8d3611..8b4bdc7 100644
--- a/frontend/src/styles/tokens.css
+++ b/frontend/src/styles/tokens.css
@@ -28,11 +28,6 @@
--leading-normal: 1.5;
--leading-relaxed: 1.75;
- --radius-sm: 3px;
- --radius-md: 4px;
- --radius-lg: 6px;
- --radius-xl: 8px;
-
--width-xs: 360px;
--width-sm: 480px;
--width-md: 760px;
@@ -42,11 +37,7 @@
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-md: 0 2px 8px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.15);
- --shadow-focus: 0 0 0 2px var(--accent-muted);
-
- --transition-fast: 0.1s ease;
- --transition-normal: 0.15s ease;
- --transition-slow: 0.25s ease;
+ --shadow-focus: 0 0 0 2px var(--secondary-muted);
--z-modal: 1000;
--overlay-bg: rgba(0, 0, 0, 0.5);
@@ -91,6 +82,12 @@
--warning-border: #d4a03c;
--warning-text: #856404;
+ --danger-bg: #c00;
+ --danger-bg-hover: #a00;
+
+ --info-bg: #e0f2fe;
+ --info-text: #0369a1;
+
--border-color-light: var(--border-dark);
}
@@ -133,5 +130,11 @@
--warning-bg: #1f1a0f;
--warning-border: #3d351a;
--warning-text: #c6b87b;
+
+ --danger-bg: #ff8a8a;
+ --danger-bg-hover: #ff6b6b;
+
+ --info-bg: #0c2d48;
+ --info-text: #7bc6f0;
}
}
diff --git a/frontend/src/tests/oauth-registration.test.ts b/frontend/src/tests/oauth-registration.test.ts
index 2876749..aca1e6c 100644
--- a/frontend/src/tests/oauth-registration.test.ts
+++ b/frontend/src/tests/oauth-registration.test.ts
@@ -149,10 +149,10 @@ describe("OAuth Registration Flow", () => {
const Register = (await import("../routes/Register.svelte"))
.default;
- render(Register);
+ const { container } = render(Register);
await waitFor(() => {
- expect(screen.getByText(/loading/i)).toBeInTheDocument();
+ expect(container.querySelector(".loading")).toBeInTheDocument();
});
});