一键导入
ios-hig-mobile
Mobile-first components following Apple HIG patterns adapted for web (React/Next/PWA). Tab bars, sheets, Dynamic Type, Safe Areas, haptics.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Mobile-first components following Apple HIG patterns adapted for web (React/Next/PWA). Tab bars, sheets, Dynamic Type, Safe Areas, haptics.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Review existing Architecture Decision Records. Flag ADRs whose aging signals may have triggered given current state. Categorizes each as valid / aged / superseded and suggests follow-up actions.
Author an Architecture Decision Record (ADR). Captures decisions with implications beyond the current change — lasts months, affects multiple files, hard to reverse. Records context, alternatives considered, consequences, and aging signals so the decision can be revisited when conditions change.
4-phase loop-detection and recovery protocol. Fires when an agent detects it is stuck or repeating the same tool call with no progress — before tool-loop-detection circuit-breaks at 30 calls.
Socratic exploration of requirements before implementation. Refines spec through targeted questions. Use when user asks to 'explore options', 'refine requirements', or mentions 'unclear requirements'.
Generate structured changelog from git history. Groups commits by type, filters noise, produces Keep a Changelog format. Single source of truth — no /commands wrapper.
Generate pipe-delimited commits: Tipo|IdTarea|YYYYMMDD|Descripción. Single source of truth — no /commands wrapper.
基于 SOC 职业分类
| name | ios-hig-mobile |
| description | Mobile-first components following Apple HIG patterns adapted for web (React/Next/PWA). Tab bars, sheets, Dynamic Type, Safe Areas, haptics. |
| version | 1.0.0 |
| when | {"keywords":["mobile","ios","hig","tab bar","sheet","modal","safe area","dynamic type","haptic","native feel"]} |
| allowed-tools | ["Read","Write","Edit","Glob"] |
When the user asks for mobile components, "native feel", or iOS-style UI on web — apply HIG patterns adapted to React/Next/PWA. Use Tailwind classes plus Lucide icons. Never ship fixed-pixel text. Always use env(safe-area-inset-*).
If user wants pixel-perfect native UIKit, push back: web cannot fully replicate it. Offer the closest faithful adaptation.
For every component request:
text-[14px]-style fixed pixels, prefers-reduced-motion honored where animation exists.rem/em only. Never px for typography.env(safe-area-inset-*).navigator.vibrate is progressive enhancement — never required, never blocking.h-11 w-11 (44pt equivalent).lucide-react. Never inline custom SVG when a Lucide equivalent exists.text-[14px] or font-size: 14px → breaks Dynamic Type.pb-4 on a bottom tab bar → ignores home indicator. Use pb-[env(safe-area-inset-bottom)].lucide-react ChevronRight.Tab bar (3-5 items, fixed bottom):
import { Home, Search, Bell, User } from "lucide-react";
export function TabBar() {
return (
<nav className="fixed bottom-0 inset-x-0 bg-white/90 backdrop-blur border-t
pb-[env(safe-area-inset-bottom)] flex justify-around" role="tablist">
{[Home, Search, Bell, User].map((Icon, i) => (
<button key={i} role="tab"
className="flex flex-col items-center gap-0.5 py-2 h-11 min-w-11">
<Icon className="w-6 h-6" aria-hidden />
<span className="text-[0.625rem]">Label</span>
</button>
))}
</nav>
);
}
Nav bar (back left, action right):
import { ChevronLeft, Plus } from "lucide-react";
<header className="sticky top-0 bg-white/90 backdrop-blur
pt-[env(safe-area-inset-top)] flex items-center h-11 px-2">
<button className="h-11 w-11 grid place-items-center" aria-label="Back">
<ChevronLeft className="w-6 h-6" />
</button>
<h1 className="flex-1 text-center text-base font-semibold">Title</h1>
<button className="h-11 w-11 grid place-items-center" aria-label="Add">
<Plus className="w-6 h-6" />
</button>
</header>
<Drawer>.| SF Symbol | Lucide | SF Symbol | Lucide |
|---|---|---|---|
| chevron.right | ChevronRight | chevron.left | ChevronLeft |
| chevron.up | ChevronUp | chevron.down | ChevronDown |
| ellipsis | MoreHorizontal | plus | Plus |
| xmark | X | magnifyingglass | Search |
| person | User | person.crop.circle | UserCircle |
| gear / gearshape | Settings | bell | Bell |
| heart | Heart | star | Star |
| bookmark | Bookmark | square.and.arrow.up | Share |
| trash | Trash2 | pencil | Pencil |
| arrow.up | ArrowUp | arrow.down | ArrowDown |
| checkmark | Check | info.circle | Info |
| exclamationmark.triangle | AlertTriangle | house | Home |
| paperplane | Send | camera | Camera |
Install: npm install lucide-react. Import named only.
Use rem everywhere. iOS text styles → Tailwind:
| iOS style | Tailwind | iOS style | Tailwind |
|---|---|---|---|
| Large Title | text-[2.125rem] font-bold | Title 1 | text-[1.75rem] font-bold |
| Headline | text-[1.0625rem] font-semibold | Body | text-base |
| Subheadline | text-[0.9375rem] | Footnote | text-[0.8125rem] |
| Caption | text-xs |
html { font-size: 100%; } /* respect OS root size */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { animation-duration: 0.01ms !important; }
}
Line length: cap at max-w-[60ch] for body copy.
Root layout once: <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />. Then on every fixed-position chrome:
className="pt-[env(safe-area-inset-top)] pb-[env(safe-area-inset-bottom)] pl-[env(safe-area-inset-left)] pr-[env(safe-area-inset-right)]"
Scrollable content under fixed tab bar: pb-[calc(env(safe-area-inset-bottom)+3.5rem)].
type HapticPattern = "tap" | "success" | "warning" | "error";
const PATTERNS: Record<HapticPattern, number | number[]> = {
tap: 10,
success: [10, 40, 10],
warning: [20, 60, 20],
error: [40, 60, 40, 60, 40],
};
export function haptic(pattern: HapticPattern = "tap"): void {
if (typeof navigator === "undefined") return;
if (!("vibrate" in navigator)) return;
navigator.vibrate(PATTERNS[pattern]);
}
Usage: onClick={() => { haptic("tap"); doAction(); }}. Action must succeed without haptic firing.
Before returning generated code, confirm:
env(safe-area-inset-*)text-[14px], font-size: 14px)h-11 w-11 minimumlucide-react, not inline SVG<meta viewport ... viewport-fit=cover> documented if first install