evOo-local/apps/mobile/lib/appearance.ts
cynarAI f8b4ce4b6d
Größere Header- und Sidebar-Icons (Web + iPhone) (#172)
* Increase header and sidebar icon scale on web and mobile

Raise shared --icon-sm/md/lg tokens (~25%) for web shell chrome, widen
chat header action controls, and align Expo home/thread header glyphs
with 44pt tap targets.

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* ci: retrigger checks after flaky evo-deploy test

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>
2026-10-06 15:36:54 +02:00

83 lines
2.3 KiB
TypeScript

import {
type AppearancePreference,
normalizeAppearancePreference,
type ResolvedAppearance,
resolveAppearance,
tokensForAppearance,
UI_APPEARANCE_STORAGE_KEY,
} from "@rakazo/ui-tokens";
import * as SecureStore from "expo-secure-store";
import { Appearance, type ColorSchemeName } from "react-native";
export type { AppearancePreference, ResolvedAppearance };
let memoryPreference: AppearancePreference | null = null;
const listeners = new Set<() => void>();
function systemAppearance(scheme?: ColorSchemeName | null): ResolvedAppearance {
return (scheme ?? Appearance.getColorScheme()) === "light" ? "light" : "dark";
}
export function getCachedAppearancePreference(): AppearancePreference {
return memoryPreference ?? "system";
}
export async function loadAppearancePreference(): Promise<AppearancePreference> {
try {
const stored = await SecureStore.getItemAsync(UI_APPEARANCE_STORAGE_KEY);
memoryPreference = normalizeAppearancePreference(stored);
} catch {
memoryPreference = memoryPreference ?? "system";
}
notify();
return memoryPreference;
}
export async function setAppearancePreference(
preference: AppearancePreference,
): Promise<AppearancePreference> {
memoryPreference = preference;
try {
await SecureStore.setItemAsync(UI_APPEARANCE_STORAGE_KEY, preference);
} catch {
// Keep the in-memory preference when SecureStore is unavailable.
}
notify();
return preference;
}
export function resolveMobileAppearance(
preference: AppearancePreference = getCachedAppearancePreference(),
scheme?: ColorSchemeName | null,
): ResolvedAppearance {
return resolveAppearance(preference, systemAppearance(scheme));
}
export function mobileTokens(
preference: AppearancePreference = getCachedAppearancePreference(),
scheme?: ColorSchemeName | null,
) {
return tokensForAppearance(resolveMobileAppearance(preference, scheme));
}
/** Header and inbox nav glyphs — aligned with web `--icon-*` scale (~25% larger). */
export const mobileShellIconSizes = {
md: 22,
lg: 26,
} as const;
export function subscribeAppearance(listener: () => void): () => void {
listeners.add(listener);
return () => {
listeners.delete(listener);
};
}
function notify() {
for (const listener of listeners) listener();
}
Appearance.addChangeListener(() => {
if (getCachedAppearancePreference() === "system") notify();
});