热门角色不仅是灵感来源,更是你的效率助手。通过精挑细选的角色提示词,你可以快速生成高质量内容、提升创作灵感,并找到最契合你需求的解决方案。让创作更轻松,让价值更直接!
我们根据不同用户需求,持续更新角色库,让你总能找到合适的灵感入口。
本提示词可根据指定组件类型生成完整UI设计规范,包括视觉属性、交互状态、可访问性考虑及代码实现说明,确保文档结构清晰、专业可复用,适用于多产品线和前端开发团队参考使用。
示例采用 CSS 变量作为设计令牌,支持浅/深色主题与多产品线复用。
<!-- 主按钮:默认(可含图标与加载状态) -->
<button class="btn btn-primary btn--md" type="button" aria-live="polite">
<span class="btn__spinner" aria-hidden="true"></span>
<span class="btn__label">提交</span>
<!-- 可选图标:放在文本左侧
<svg class="btn__icon" aria-hidden="true" ...></svg>
-->
<span class="sr-only" data-status></span> <!-- 用于 aria-live 通知 -->
</button>
/* 设计令牌(示例,可根据品牌调优) */
:root {
/* 浅色主题 */
--primary-300: #A5D3FF;
--primary-500: #2D8CFF;
--primary-600: #1E7AF8;
--primary-700: #136AE0;
--primary-800: #0D58BE;
--on-primary: #FFFFFF;
--on-primary-disabled: rgba(255,255,255,0.7);
--focus-ring: #1E7AF8; /* 或品牌辅助色 */
--shadow-weak: 0 1px 2px rgba(0,0,0,0.12);
--shadow-strong: 0 2px 6px rgba(0,0,0,0.16);
--spinner-size: 1em; /* 随字号缩放 */
--spinner-stroke: 2px;
}
/* 深色主题覆盖(示例) */
@media (prefers-color-scheme: dark) {
:root {
--primary-300: #5FA0E6;
--primary-500: #2D8CFF;
--primary-600: #1E7AF8;
--primary-700: #136AE0;
--primary-800: #0D58BE;
--on-primary: #FFFFFF;
--on-primary-disabled: rgba(255,255,255,0.65);
--focus-ring: #9BC9FF;
}
}
/* 基础按钮样式 */
.btn {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "PingFang SC", "Microsoft YaHei", sans-serif;
font-weight: 600;
line-height: 1;
border: none;
border-radius: 8px;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
cursor: pointer;
user-select: none;
white-space: nowrap;
text-decoration: none;
transition: background-color 120ms ease, box-shadow 120ms ease, transform 60ms ease;
will-change: background-color, box-shadow, transform;
}
/* 尺寸 */
.btn--sm { font-size: 14px; height: 32px; padding: 0 12px; }
.btn--md { font-size: 16px; height: 40px; padding: 0 16px; }
.btn--lg { font-size: 16px; height: 48px; padding: 0 20px; }
/* 主按钮变体 */
.btn-primary {
background-color: var(--primary-600);
color: var(--on-primary);
box-shadow: var(--shadow-weak);
}
/* 悬停:仅在有 hover 能力设备启用 */
@media (hover: hover) {
.btn-primary:hover:not(:disabled):not([aria-busy="true"]) {
background-color: var(--primary-700);
box-shadow: var(--shadow-strong);
}
}
/* 聚焦可见 */
.btn-primary:focus-visible {
outline: 2px solid var(--focus-ring);
outline-offset: 2px;
}
/* 按下(激活) */
.btn-primary:active:not(:disabled):not([aria-busy="true"]) {
background-color: var(--primary-800);
box-shadow: var(--shadow-weak);
transform: scale(0.98);
}
/* 禁用 */
.btn-primary:disabled {
background-color: var(--primary-300);
color: var(--on-primary-disabled);
box-shadow: none;
cursor: not-allowed;
}
/* 文本溢出处理 */
.btn__label {
overflow: hidden;
text-overflow: ellipsis;
}
/* 预留 spinner 空间,避免布局跳动 */
.btn__spinner {
width: var(--spinner-size);
height: var(--spinner-size);
border-radius: 50%;
border: var(--spinner-stroke) solid rgba(255,255,255,0.35);
border-top-color: currentColor;
display: inline-block;
visibility: hidden; /* 默认不占位可改为 visibility 以保留空间 */
opacity: 0;
transition: opacity 120ms ease, visibility 0s linear 120ms;
}
/* 加载态样式:显示 spinner,禁用交互 */
.btn-primary[aria-busy="true"] {
pointer-events: none;
}
.btn-primary[aria-busy="true"] .btn__spinner {
visibility: visible;
opacity: 1;
animation: spin 600ms linear infinite;
transition: opacity 120ms ease;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
/* 低动画偏好 */
@media (prefers-reduced-motion: reduce) {
.btn { transition: none; }
.btn-primary:active { transform: none; }
.btn__spinner { animation: none; }
}
/* 强制高对比模式兼容(Windows) */
@media (forced-colors: active) {
.btn-primary {
background: ButtonFace;
color: ButtonText;
box-shadow: none;
}
.btn-primary:focus-visible {
outline: 2px solid Highlight;
}
}
// 最小交互逻辑:加载态管理与无障碍提示
function setButtonLoading(btn, isLoading, statusText = '正在提交…') {
if (!(btn instanceof HTMLButtonElement)) return;
const statusNode = btn.querySelector('[data-status]');
const spinner = btn.querySelector('.btn__spinner');
if (isLoading) {
btn.setAttribute('aria-busy', 'true');
btn.disabled = true; // 防止重复点击
if (statusNode) statusNode.textContent = statusText; // aria-live=polite 将提示
if (spinner) spinner.style.visibility = 'visible'; // 如需强制保留空间可在 CSS 中始终可见但透明
} else {
btn.removeAttribute('aria-busy');
btn.disabled = false;
if (statusNode) statusNode.textContent = '';
if (spinner) {
spinner.style.visibility = ''; // 复位
}
}
}
// 使用示例
const submitBtn = document.querySelector('.btn-primary');
submitBtn?.addEventListener('click', async () => {
setButtonLoading(submitBtn, true, '正在提交…');
try {
// 执行异步操作
await new Promise(res => setTimeout(res, 1500));
// 成功后可更新文案或状态
} catch (e) {
// 失败处理:提示错误
} finally {
setButtonLoading(submitBtn, false);
}
});
代码规范与实现要点:
建议通过设计令牌提供主题化支持(浅色/深色/高对比模式),以下为默认值与命名示例。
结构层级
颜色(Design Tokens)
字体与字号
尺寸规格(高度,含内边距,不含外边距)
间距与布局
视觉变体(可选)
默认(Default)
悬停(Hover)
聚焦(Focus)
激活/输入中(Active/Typing)
已填(Filled)
错误(Invalid)
警示(Warning,可选)
成功(Valid,可选)
禁用(Disabled)
只读(Read-only)
附加行为
语义与关联
对比度
键盘与屏幕阅读器
输入类型与辅助属性
错误信息文案规范
示例一:基础输入(带标签、占位、计数、校验、错误提示)
<div class="field" data-size="m">
<label for="email" class="field__label">
邮箱地址 <span class="field__required" aria-hidden="true">*</span>
</label>
<div class="field__control">
<!-- 可选前缀 -->
<!-- <span class="field__prefix" aria-hidden="true">@</span> -->
<input
id="email"
name="email"
type="email"
class="field__input"
placeholder="name@example.com"
required
aria-required="true"
maxlength="100"
autocomplete="email"
inputmode="email"
aria-invalid="false"
aria-describedby="email_helper email_counter email_error"
/>
<!-- 可选后缀或清除按钮/密码显隐按钮 -->
<!-- <button type="button" class="field__clear" aria-label="清除输入" hidden>×</button> -->
</div>
<div id="email_helper" class="field__helper">
我们仅用于账户通知,不会发送垃圾邮件。
</div>
<div class="field__meta">
<div id="email_error" class="field__error" aria-live="polite"></div>
<div id="email_counter" class="field__counter" aria-live="polite" aria-atomic="true">0/100</div>
</div>
</div>
CSS(使用设计令牌,支持浅/深主题)
:root {
--color-bg-surface: #FFFFFF;
--color-bg-input: #FFFFFF;
--color-border: #C9CED6;
--color-border-hover: #AEB6C2;
--color-border-focus: #2563EB;
--color-text: #0F172A;
--color-placeholder: #6B7280;
--color-label: #334155;
--color-helper: #64748B;
--color-error: #DC2626;
--color-success: #16A34A;
--focus-ring: rgba(37, 99, 235, 0.35);
--radius: 6px;
--space-2: 8px;
--space-1: 4px;
--height-s: 36px;
--height-m: 40px;
--height-l: 48px;
}
.field { width: 100%; }
.field__label {
display: block;
margin-bottom: 6px;
color: var(--color-label);
font-size: 12px;
line-height: 18px;
}
.field__required { color: var(--color-error); margin-left: 4px; }
.field__control {
position: relative;
display: flex;
align-items: center;
background: var(--color-bg-input);
border: 1px solid var(--color-border);
border-radius: var(--radius);
transition: border-color 120ms ease, box-shadow 120ms ease;
}
.field[data-size="s"] .field__control { height: var(--height-s); }
.field[data-size="m"] .field__control { height: var(--height-m); }
.field[data-size="l"] .field__control { height: var(--height-l); }
.field__input {
flex: 1;
width: 100%;
border: 0;
outline: none;
background: transparent;
color: var(--color-text);
font-size: 14px;
line-height: 20px;
padding: 0 12px;
}
.field__input::placeholder { color: var(--color-placeholder); }
.field__control:hover { border-color: var(--color-border-hover); }
.field__input:focus-visible + .field__suffix,
.field__input:focus-visible {
/* focus ring on container for robust visuals */
}
.field__control:has(.field__input:focus-visible) {
border-color: var(--color-border-focus);
box-shadow: 0 0 0 3px var(--focus-ring);
}
.field__helper {
margin-top: 6px;
color: var(--color-helper);
font-size: 12px;
line-height: 16px;
}
.field__meta {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-top: 4px;
}
.field__error {
min-height: 16px;
color: var(--color-error);
font-size: 12px;
line-height: 16px;
}
.field__counter {
color: var(--color-helper);
font-size: 12px;
line-height: 16px;
}
/* 错误状态(容器类控制) */
.field.is-invalid .field__control {
border-color: var(--color-error);
box-shadow: none;
}
.field.is-disabled .field__control {
background: #F1F5F9;
border-color: #E2E8F0;
}
.field.is-disabled .field__input {
color: #94A3B8;
cursor: not-allowed;
}
JS(校验、计数、a11y 更新)
function initTextField(root) {
const input = root.querySelector('.field__input');
const error = root.querySelector('.field__error');
const counter = root.querySelector('.field__counter');
const max = input.maxLength > 0 ? input.maxLength : null;
function updateCounter() {
if (!counter || !max) return;
const len = input.value.length;
counter.textContent = `${len}/${max}`;
}
function validate() {
let msg = '';
// HTML 原生校验
if (input.validity.valueMissing) {
msg = '此字段为必填项。';
} else if (input.type === 'email' && input.value && input.validity.typeMismatch) {
msg = '请输入有效的邮箱地址(例如 name@example.com)。';
} else if (input.value && input.minLength && input.value.length < input.minLength) {
msg = `至少输入 ${input.minLength} 个字符。`;
} else if (max && input.value.length > max) {
msg = `最多输入 ${max} 个字符。`;
}
const invalid = !!msg;
root.classList.toggle('is-invalid', invalid);
input.setAttribute('aria-invalid', invalid ? 'true' : 'false');
if (error) error.textContent = msg;
}
input.addEventListener('input', () => {
updateCounter();
// 实时但不打扰:仅在已输入内容后做轻量校验
validate();
});
input.addEventListener('blur', validate);
// 初始化
updateCounter();
validate();
}
document.querySelectorAll('.field').forEach(initTextField);
实现要点与规范
扩展变体(可选)
此规范保证跨产品线的复用与一致性,通过令牌化的视觉属性、标准化的状态与可访问性处理,以及清晰的开发示例,支持快速实现与主题扩展。
组件类型:标签页导航(Tabs,水平为主,支持宽度自适应、溢出处理、键盘导航与焦点管理)
设计优先级(从高到低):
适用范围:多产品线的顶部标签导航;支持内容面板切换、可滚动标签列、移动端触控与桌面端键盘/鼠标。
采用设计令牌(CSS变量)以保证跨产品一致性与可复用。
容器与方向
尺寸与间距
字体
颜色(浅色主题为例,深色主题需对应反转)
边框与圆角
截断与徽标
动效
默认(Rest)
悬停(Hover)
聚焦(Focus-visible)
选中(Active / Selected)
按下(Pressed)
禁用(Disabled)
溢出按钮(左右导航)
触控反馈(移动端)
溢出处理交互策略(两种可选,可并存)
示例:滚动型 Tabs(带溢出左右按钮),语义与键盘完整,使用设计令牌
HTML
<div class="tabs" dir="ltr">
<div class="tabs-bar" role="tablist" aria-orientation="horizontal">
<button class="overflow-btn prev" aria-label="Scroll left" disabled></button>
<div class="tabs-scroll" data-scroll>
<!-- 每个 tab 使用 button + role="tab"(可获得可点击与可聚焦语义) -->
<button id="tab-1" role="tab" class="tab is-selected" aria-selected="true"
aria-controls="panel-1" tabindex="0" title="概览">概览</button>
<button id="tab-2" role="tab" class="tab" aria-selected="false"
aria-controls="panel-2" tabindex="-1" title="报表与分析">报表与分析</button>
<button id="tab-3" role="tab" class="tab" aria-selected="false"
aria-controls="panel-3" tabindex="-1" title="设置">设置</button>
<!-- ... 更多标签 -->
</div>
<button class="overflow-btn next" aria-label="Scroll right"></button>
</div>
<section id="panel-1" role="tabpanel" aria-labelledby="tab-1">面板内容1</section>
<section id="panel-2" role="tabpanel" aria-labelledby="tab-2" hidden>面板内容2</section>
<section id="panel-3" role="tabpanel" aria-labelledby="tab-3" hidden>面板内容3</section>
</div>
CSS(设计令牌与样式)
:root {
--tab.height: 44px;
--tab.padding.inline: 16px;
--tab.padding.block: 10px;
--tab.minWidth: 72px;
--tab.maxWidth: 240px;
--tab.gap: 8px;
--tab.radius: 6px;
--tab.indicator.height: 2px;
--tab.font.size: 14px;
--tab.font.lineHeight: 1.5;
--tab.font.weight: 500;
--tab.font.weight.active: 600;
--color.tab.text: #1F2937;
--color.tab.text.active: #111827;
--color.tab.text.disabled: #9CA3AF;
--color.tab.bg.hover: #F3F4F6;
--color.tabbar.border: #E5E7EB;
--color.tab.indicator: #2563EB;
--color.overflow.icon: #6B7280;
--color.overflow.icon.hover: #111827;
--color.overflow.bg.hover: #F3F4F6;
--focus.ring: #2563EB;
}
.tabs { display: flex; flex-direction: column; gap: 12px; }
.tabs-bar {
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
border-bottom: 1px solid var(--color.tabbar.border);
contain: content; /* 性能优化:限制布局影响范围 */
}
.tabs-scroll {
display: flex;
gap: var(--tab.gap);
overflow-x: auto;
scrollbar-width: none; /* Firefox 隐藏滚动条 */
}
.tabs-scroll::-webkit-scrollbar { display: none; } /* WebKit 隐藏滚动条 */
/* 渐隐遮罩:可选(结合 mask 或伪元素) */
.tabs-scroll {
-webkit-mask-image: linear-gradient(to right, transparent 0, black 24px, black calc(100% - 24px), transparent 100%);
mask-image: linear-gradient(to right, transparent 0, black 24px, black calc(100% - 24px), transparent 100%);
}
.tab {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
height: var(--tab.height);
padding: var(--tab.padding.block) var(--tab.padding.inline);
min-width: var(--tab.minWidth);
max-width: var(--tab.maxWidth);
border: 0;
border-radius: var(--tab.radius);
background: transparent;
color: var(--color.tab.text);
font-size: var(--tab.font.size);
line-height: var(--tab.font.lineHeight);
font-weight: var(--tab.font.weight);
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
cursor: pointer;
}
.tab:hover { background: var(--color.tab.bg.hover); }
.tab:focus-visible {
outline: 2px solid var(--focus.ring);
outline-offset: 2px;
}
/* 选中态:底部指示条 */
.tab.is-selected {
font-weight: var(--tab.font.weight.active);
color: var(--color.tab.text.active);
}
.tab.is-selected::after {
content: "";
position: absolute;
left: 8px; right: 8px; bottom: -1px;
height: var(--tab.indicator.height);
background: var(--color.tab.indicator);
border-radius: 1px;
}
.tab[aria-disabled="true"] {
color: var(--color.tab.text.disabled);
cursor: not-allowed;
}
.overflow-btn {
inline-size: 32px; block-size: 32px; /* 触控可改 40–44 */
border: 0; border-radius: 6px;
background: transparent;
cursor: pointer;
position: relative;
}
.overflow-btn:focus-visible { outline: 2px solid var(--focus.ring); outline-offset: 2px; }
.overflow-btn:hover { background: var(--color.overflow.bg.hover); }
.overflow-btn[disabled] { opacity: 0.5; cursor: not-allowed; }
/* 使用伪元素绘制箭头,或替换为内嵌SVG */
.overflow-btn.prev::before, .overflow-btn.next::before {
content: "";
display: inline-block;
width: 0; height: 0;
border-top: 6px solid transparent; border-bottom: 6px solid transparent;
border-inline-start: 6px solid var(--color.overflow.icon); /* 三角形箭头 */
}
.overflow-btn.next::before {
transform: scaleX(-1); /* 镜像为右箭头 */
}
/* 面板样式示例 */
[role="tabpanel"] { padding: 12px 0; }
[role="tabpanel"][hidden] { display: none; }
/* 优化:减少动画 */
@media (prefers-reduced-motion: reduce) {
.tab.is-selected::after { transition: none; }
}
JavaScript(键盘与溢出滚动、roving tabindex、激活与面板切换)
class Tabs {
constructor(root) {
this.root = root;
this.tablist = root.querySelector('[role="tablist"]');
this.scroll = root.querySelector('.tabs-scroll');
this.prevBtn = root.querySelector('.overflow-btn.prev');
this.nextBtn = root.querySelector('.overflow-btn.next');
this.tabs = Array.from(root.querySelectorAll('[role="tab"]'));
this.panels = Array.from(root.querySelectorAll('[role="tabpanel"]'));
this._bind();
this._updateOverflow();
this._ensureSelectedVisible();
this._observeResize();
}
_bind() {
this.tablist.addEventListener('keydown', (e) => this._onKeydown(e), { passive: true });
this.tabs.forEach(tab => {
tab.addEventListener('click', () => this.selectTab(tab));
});
// 溢出滚动
this.prevBtn?.addEventListener('click', () => this._scrollBy(-1));
this.nextBtn?.addEventListener('click', () => this._scrollBy(1));
this.scroll?.addEventListener('scroll', () => this._updateOverflow(), { passive: true });
}
_onKeydown(e) {
const rtl = getComputedStyle(this.tablist).direction === 'rtl';
const currentIndex = this.tabs.indexOf(document.activeElement);
// 仅在 tab 获得焦点时处理
if (currentIndex === -1) return;
const key = e.key;
let nextIndex = null;
if (key === 'ArrowRight') {
nextIndex = rtl ? currentIndex - 1 : currentIndex + 1;
} else if (key === 'ArrowLeft') {
nextIndex = rtl ? currentIndex + 1 : currentIndex - 1;
} else if (key === 'Home') {
nextIndex = 0;
} else if (key === 'End') {
nextIndex = this.tabs.length - 1;
} else if (key === 'Enter' || key === ' ') {
e.preventDefault();
this.selectTab(this.tabs[currentIndex]);
return;
} else if (key === 'PageUp' && e.ctrlKey) {
nextIndex = (currentIndex - 1 + this.tabs.length) % this.tabs.length;
} else if (key === 'PageDown' && e.ctrlKey) {
nextIndex = (currentIndex + 1) % this.tabs.length;
}
if (nextIndex != null) {
e.preventDefault();
nextIndex = Math.max(0, Math.min(this.tabs.length - 1, nextIndex));
const nextTab = this.tabs[nextIndex];
this._moveFocus(nextTab);
this._scrollIntoView(nextTab);
}
}
selectTab(tab) {
if (tab.getAttribute('aria-disabled') === 'true') return;
// 更新选中状态与 roving tabindex
this.tabs.forEach(t => {
const selected = t === tab;
t.classList.toggle('is-selected', selected);
t.setAttribute('aria-selected', String(selected));
t.tabIndex = selected ? 0 : -1;
});
// 面板切换
const panelId = tab.getAttribute('aria-controls');
this.panels.forEach(panel => {
const active = panel.id === panelId;
panel.toggleAttribute('hidden', !active);
if (!active) panel.tabIndex = -1;
else panel.tabIndex = 0; // 若需将焦点移入面板,可在此 focus()
});
this._scrollIntoView(tab);
this._updateOverflow();
}
_moveFocus(tab) { tab.focus({ preventScroll: true }); }
_scrollBy(direction) {
const step = this.scroll.clientWidth * 0.8; // 按容器宽度滚动
const delta = direction * step;
this.scroll.scrollBy({ left: delta, behavior: this._reducedMotion() ? 'auto' : 'smooth' });
}
_scrollIntoView(tab) {
const rect = tab.getBoundingClientRect();
const sRect = this.scroll.getBoundingClientRect();
const isLeftOverflow = rect.left < sRect.left + 8;
const isRightOverflow = rect.right > sRect.right - 8;
if (isLeftOverflow) {
const offset = rect.left - sRect.left - 8;
this.scroll.scrollBy({ left: offset, behavior: this._reducedMotion() ? 'auto' : 'smooth' });
} else if (isRightOverflow) {
const offset = rect.right - sRect.right + 8;
this.scroll.scrollBy({ left: offset, behavior: this._reducedMotion() ? 'auto' : 'smooth' });
}
}
_updateOverflow() {
if (!this.scroll || !this.prevBtn || !this.nextBtn) return;
const maxScroll = this.scroll.scrollWidth - this.scroll.clientWidth;
const x = Math.round(this.scroll.scrollLeft);
this.prevBtn.disabled = x <= 0;
this.nextBtn.disabled = x >= maxScroll - 1;
}
_observeResize() {
// ResizeObserver:尺寸变化时更新溢出状态
const ro = new ResizeObserver(() => {
this._updateOverflow();
this._ensureSelectedVisible();
});
ro.observe(this.scroll);
ro.observe(this.tablist);
this._ro = ro;
}
_ensureSelectedVisible() {
const selected = this.tabs.find(t => t.classList.contains('is-selected'));
if (selected) this._scrollIntoView(selected);
}
_reducedMotion() {
return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
}
}
// 初始化(支持多实例)
document.querySelectorAll('.tabs').forEach(el => new Tabs(el));
组件代码规范与扩展建议
此规范确保标签页导航在多设备与多产品线下具备一致的视觉与交互体验,满足可用性、响应式、可访问性与性能优化要求,并提供直接可用的实现参考。
帮助用户高效制定UI组件设计规范,确保设计的一致性和高质量交付,同时满足视觉美观、交互体验和代码实现等多维需求。
快速生成完整的设计规范文档,减少重复性工作,专注于设计创新。
为产品输出清晰可执行的UI组件规则,确保团队一致性协作。
借助自动生成的代码说明,提高开发效率,减少对设计师反复沟通的时间。
将模板生成的提示词复制粘贴到您常用的 Chat 应用(如 ChatGPT、Claude 等),即可直接对话使用,无需额外开发。适合个人快速体验和轻量使用场景。
把提示词模板转化为 API,您的程序可任意修改模板参数,通过接口直接调用,轻松实现自动化与批量处理。适合开发者集成与业务系统嵌入。
在 MCP client 中配置对应的 server 地址,让您的 AI 应用自动调用提示词模板。适合高级用户和团队协作,让提示词在不同 AI 工具间无缝衔接。
免费获取高级提示词-优惠即将到期