eebf3b3334
Co-Authored-By: Claude Code <noreply@anthropic.com>
630 lines
19 KiB
Vue
630 lines
19 KiB
Vue
<!-- 展示位本地实时预览(UI-01 Task 7):表单草稿 → 桌面/手机双框预览。
|
||
· 纯本地:不调用任何接口、不写展示位、不上报浏览——数据为内置示例
|
||
(3 张渐变示意照片 + 相册标题占位),未保存修改经 props 即时反映;
|
||
· 与生产组件共享展示结构:类名/结构镜像 viewer 嵌入页(embed-root/
|
||
embed-head/embed-stage/embed-foot + loader 收起把手),样式随
|
||
viewer 同步维护,非另起一套视觉;停靠几何由 buildPreviewPlacement
|
||
纯函数产出(与 loader wrapper 同规则);
|
||
· mobile 框模拟 <480px 窄屏:强制 sm + 默认收起(§5.4),把手可点击
|
||
本地展开演示(用户选择优先于默认值——仅预览内状态);
|
||
· zIndex 徽标 + 框内低层级示意元素(z-index 900)直观反映层级配置;
|
||
· 暂停/查看相册等控件为装饰(disabled),不触发任何动作。 -->
|
||
<template>
|
||
<div class="embed-preview" :class="`is-${mode}`">
|
||
<div
|
||
class="embed-preview-frame"
|
||
:data-test="mode === 'desktop' ? 'embed-preview-desktop' : 'embed-preview-mobile'"
|
||
>
|
||
<div v-if="mode === 'desktop'" class="embed-preview-chrome" aria-hidden="true">
|
||
<span class="embed-preview-dot"></span>
|
||
<span class="embed-preview-dot"></span>
|
||
<span class="embed-preview-dot"></span>
|
||
<span class="embed-preview-url">www.example.com</span>
|
||
</div>
|
||
<div v-else class="embed-preview-chrome embed-preview-chrome--phone" aria-hidden="true">
|
||
<span class="embed-preview-notch"></span>
|
||
</div>
|
||
|
||
<div class="embed-preview-body">
|
||
<!-- 宿主页面示意内容(纯装饰) -->
|
||
<div class="embed-preview-page" aria-hidden="true">
|
||
<span class="embed-preview-page-title"></span>
|
||
<span class="embed-preview-page-line"></span>
|
||
<span class="embed-preview-page-line is-short"></span>
|
||
<span class="embed-preview-page-banner"></span>
|
||
<span class="embed-preview-page-line"></span>
|
||
</div>
|
||
<!-- 低层级宿主元素示意(z-index 900):层级配置直观可见 -->
|
||
<span
|
||
v-if="mode === 'desktop'"
|
||
class="embed-preview-chat"
|
||
aria-hidden="true"
|
||
data-test="embed-preview-chat"
|
||
>
|
||
{{ $t('embedSlotsManage.preview.chatMock') }}
|
||
</span>
|
||
|
||
<span class="embed-preview-badge" data-test="embed-preview-badge">
|
||
{{ $t('embedSlotsManage.preview.badge') }}
|
||
</span>
|
||
<span class="embed-preview-zindex" data-test="embed-preview-zindex">
|
||
z-index {{ placement.zIndex }}
|
||
</span>
|
||
|
||
<!-- 悬浮组件本体(几何随草稿即时变化) -->
|
||
<div
|
||
class="embed-preview-dock"
|
||
:class="[`is-${placement.side}`, { 'is-v2': isV2 }]"
|
||
:style="widgetStyle"
|
||
data-test="embed-preview-widget"
|
||
>
|
||
<!-- UI-04 v2:真实组件预览(iframe 载 viewer /embed-preview——真实
|
||
EmbedStream/引擎/气泡层,样例数据注入;配置经 postMessage 实时
|
||
更新,§8.2「preview 用真实展示组件,数据源注入」)。 -->
|
||
<div v-if="isV2 && !isCollapsed" class="embed-preview-v2frame" data-test="embed-preview-v2">
|
||
<iframe
|
||
ref="previewFrame"
|
||
:src="previewSrc"
|
||
title="PhotoLive v2 preview"
|
||
data-test="embed-preview-v2-iframe"
|
||
></iframe>
|
||
</div>
|
||
<div
|
||
v-else-if="isCollapsed && isV2"
|
||
class="embed-handle embed-handle--v2"
|
||
data-test="embed-preview-handle"
|
||
role="button"
|
||
tabindex="0"
|
||
@click="expand"
|
||
@keydown.enter.prevent="expand"
|
||
@keydown.space.prevent="expand"
|
||
>
|
||
<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true" focusable="false">
|
||
<path
|
||
fill="#1a73e8"
|
||
d="M9 2 7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"
|
||
/>
|
||
</svg>
|
||
<span>{{ $t('embedSlotsManage.preview.handleText') }}</span>
|
||
</div>
|
||
<div
|
||
v-else-if="isCollapsed"
|
||
class="embed-handle"
|
||
data-test="embed-preview-handle"
|
||
role="button"
|
||
tabindex="0"
|
||
@click="expand"
|
||
@keydown.enter.prevent="expand"
|
||
@keydown.space.prevent="expand"
|
||
>
|
||
<svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" focusable="false">
|
||
<path
|
||
fill="#ffffff"
|
||
d="M9 2 7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"
|
||
/>
|
||
</svg>
|
||
<span>{{ $t('embedSlotsManage.preview.handleText') }}</span>
|
||
</div>
|
||
<!-- 镜像 viewer EmbedPage 结构:embed-root > embed-head + embed-carousel -->
|
||
<div v-else class="embed-root">
|
||
<div class="embed-head">
|
||
<span class="embed-heading">{{ $t('embedSlotsManage.preview.widgetTitle') }}</span>
|
||
<button
|
||
type="button"
|
||
class="embed-close"
|
||
:aria-label="$t('embedSlotsManage.preview.collapseLabel')"
|
||
data-test="embed-preview-collapse"
|
||
@click="collapse"
|
||
>
|
||
<svg
|
||
viewBox="0 0 24 24"
|
||
width="14"
|
||
height="14"
|
||
aria-hidden="true"
|
||
focusable="false"
|
||
>
|
||
<path
|
||
fill="currentColor"
|
||
d="M18.3 5.71 12 12.01l-6.3-6.3-1.4 1.41 6.29 6.3-6.3 6.3 1.42 1.4 6.29-6.29 6.3 6.3 1.4-1.42-6.3-6.29 6.3-6.3z"
|
||
/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<div class="embed-carousel">
|
||
<div
|
||
class="embed-stage"
|
||
:class="placement.imageFit === 'cover' ? 'is-cover' : 'is-contain'"
|
||
data-test="embed-preview-stage"
|
||
>
|
||
<!-- 示例照片为 1:1 渐变色块:contain 完整展示(衬中性深色底)、
|
||
cover 裁切填满——适配配置即时可见 -->
|
||
<div class="embed-preview-photo" :style="mockSlides[0].gradient">
|
||
<span>{{ $t('embedSlotsManage.preview.photoLabel', { n: 1 }) }}</span>
|
||
</div>
|
||
</div>
|
||
<footer class="embed-foot">
|
||
<p class="embed-title" data-test="embed-preview-title">{{ albumTitle }}</p>
|
||
<div class="embed-foot-row">
|
||
<span class="embed-indicator" data-test="embed-preview-indicator">01 / 03</span>
|
||
<div class="embed-foot-actions">
|
||
<button type="button" class="embed-foot-btn" disabled aria-disabled="true">
|
||
<svg
|
||
viewBox="0 0 24 24"
|
||
width="14"
|
||
height="14"
|
||
aria-hidden="true"
|
||
focusable="false"
|
||
>
|
||
<path fill="currentColor" d="M6 5h4v14H6zm8 0h4v14h-4z" />
|
||
</svg>
|
||
</button>
|
||
<span class="embed-foot-link is-disabled" data-test="embed-preview-view">
|
||
{{ $t('embedSlotsManage.preview.viewAlbum') }}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="embed-preview-caption">
|
||
<span>{{
|
||
mode === 'desktop'
|
||
? $t('embedSlotsManage.preview.desktop')
|
||
: $t('embedSlotsManage.preview.mobile')
|
||
}}</span>
|
||
<span v-if="mode === 'mobile'" class="embed-preview-caption-hint">
|
||
{{ $t('embedSlotsManage.preview.collapsedHint') }}
|
||
</span>
|
||
<!-- 工具区(§8.2:仅管理预览,不在实际组件):模拟点赞事件(测试模拟)。 -->
|
||
<button
|
||
v-if="isV2 && mode === 'desktop'"
|
||
type="button"
|
||
class="embed-preview-sim"
|
||
data-test="embed-preview-sim-like"
|
||
@click="simulateLike"
|
||
>
|
||
{{ $t('embedSlotsManage.preview.simLike') }}
|
||
</button>
|
||
<span v-if="isV2" class="embed-preview-caption-hint">
|
||
{{ $t('embedSlotsManage.preview.sampleDataHint') }}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { computed, ref, watch } from 'vue'
|
||
import {
|
||
buildPreviewPlacement,
|
||
buildPreviewWidgetStyle,
|
||
clampScrollSpeed,
|
||
embedOriginFromEnv,
|
||
type EmbedSettingsDraft
|
||
} from '@/utils/system/embedSlots'
|
||
|
||
const props = defineProps<{
|
||
/** 表单草稿(未保存修改即时反映) */
|
||
draft: EmbedSettingsDraft
|
||
/** 桌面(按配置)/ 手机(<480px 窄屏行为) */
|
||
mode: 'desktop' | 'mobile'
|
||
/** 相册标题占位(编辑已绑定相册时传入,否则词条占位) */
|
||
albumTitle: string
|
||
}>()
|
||
|
||
/** 示例照片(1:1 渐变色块;仅第 1 帧上屏,指示器按 3 帧示意) */
|
||
const mockSlides = [
|
||
{ gradient: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 60%, #d946ef 100%)' },
|
||
{ gradient: 'linear-gradient(135deg, #0ea5e9 0%, #2563eb 60%, #1d4ed8 100%)' },
|
||
{ gradient: 'linear-gradient(135deg, #f59e0b 0%, #ef4444 60%, #db2777 100%)' }
|
||
]
|
||
|
||
const placement = computed(() => buildPreviewPlacement(props.draft, props.mode))
|
||
const widgetStyle = computed(() => buildPreviewWidgetStyle(placement.value))
|
||
|
||
// ── UI-04 v2 真实组件预览(§8.2)──
|
||
const isV2 = computed(() => props.draft.displayMode === 'vertical-stream')
|
||
const previewFrame = ref<HTMLIFrameElement | null>(null)
|
||
const embedOrigin = embedOriginFromEnv(import.meta.env)
|
||
|
||
/** 预览 iframe src:初始配置经查询(速度/气泡/语言);后续更新走
|
||
* postMessage(不整页重载,避免滚动位置闪烁)。 */
|
||
const previewSrc = computed(() => {
|
||
const params = new URLSearchParams({
|
||
speed: String(clampScrollSpeed(props.draft.scrollSpeed)),
|
||
lang: props.draft.lang === 'auto' ? 'zh-CN' : props.draft.lang
|
||
})
|
||
if (!props.draft.reactionsEnabled) params.set('reactions', 'off')
|
||
return `${embedOrigin}/embed-preview?${params.toString()}`
|
||
})
|
||
|
||
function postPreview(payload: Record<string, unknown>): void {
|
||
previewFrame.value?.contentWindow?.postMessage(
|
||
{ photolivePreview: true, ...payload },
|
||
embedOrigin
|
||
)
|
||
}
|
||
|
||
/** 草稿速度/气泡变化 → 实时推送(不发请求不写展示位,纯预览内生效)。 */
|
||
watch(
|
||
() => [props.draft.scrollSpeed, props.draft.reactionsEnabled] as const,
|
||
([speed, reactions]) => {
|
||
if (!isV2.value) return
|
||
postPreview({ type: 'config', speed: clampScrollSpeed(speed), reactions })
|
||
}
|
||
)
|
||
|
||
/** 模拟点赞(§8.2 工具区按钮;事件为测试模拟,注入真实校验管线)。 */
|
||
function simulateLike(): void {
|
||
postPreview({ type: 'burst', photoIndex: -1 })
|
||
}
|
||
|
||
/** 把手/关闭仅切换预览内展开态(用户选择优先于默认值;不持久化) */
|
||
const expanded = ref(false)
|
||
const isCollapsed = computed(() => placement.value.collapsed && !expanded.value)
|
||
watch(
|
||
() => placement.value.collapsed,
|
||
() => {
|
||
expanded.value = false
|
||
}
|
||
)
|
||
function expand(): void {
|
||
expanded.value = true
|
||
}
|
||
function collapse(): void {
|
||
expanded.value = false
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.embed-preview {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
}
|
||
.embed-preview-frame {
|
||
position: relative;
|
||
display: flex;
|
||
flex-direction: column;
|
||
border: 1px solid #d1d5db;
|
||
border-radius: 8px;
|
||
overflow: hidden;
|
||
background: #f9fafb;
|
||
}
|
||
.is-desktop .embed-preview-frame {
|
||
width: 440px; /* EMBED_PREVIEW_FRAME_WIDTH.desktop(buildPreviewPlacement 视口宽) */
|
||
height: 380px;
|
||
}
|
||
.is-mobile .embed-preview-frame {
|
||
width: 375px; /* EMBED_PREVIEW_FRAME_WIDTH.mobile */
|
||
height: 320px;
|
||
margin: 0 auto;
|
||
}
|
||
.embed-preview-chrome {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
padding: 6px 10px;
|
||
background: #e5e7eb;
|
||
border-bottom: 1px solid #d1d5db;
|
||
}
|
||
.embed-preview-dot {
|
||
width: 8px;
|
||
height: 8px;
|
||
border-radius: 50%;
|
||
background: #9ca3af;
|
||
}
|
||
.embed-preview-url {
|
||
margin-left: 8px;
|
||
padding: 1px 10px;
|
||
border-radius: 999px;
|
||
background: #f9fafb;
|
||
color: #6b7280;
|
||
font-size: 10px;
|
||
line-height: 16px;
|
||
}
|
||
.embed-preview-chrome--phone {
|
||
justify-content: center;
|
||
}
|
||
.embed-preview-notch {
|
||
width: 90px;
|
||
height: 12px;
|
||
border-radius: 0 0 10px 10px;
|
||
background: #d1d5db;
|
||
}
|
||
.embed-preview-body {
|
||
position: relative;
|
||
flex: 1;
|
||
overflow: hidden;
|
||
background: linear-gradient(180deg, #ffffff 0%, #f3f4f6 100%);
|
||
}
|
||
/* 宿主页面示意内容(纯装饰灰度块) */
|
||
.embed-preview-page {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
padding: 14px 16px;
|
||
}
|
||
.embed-preview-page-title {
|
||
width: 40%;
|
||
height: 12px;
|
||
border-radius: 4px;
|
||
background: #d1d5db;
|
||
}
|
||
.embed-preview-page-line {
|
||
width: 88%;
|
||
height: 8px;
|
||
border-radius: 4px;
|
||
background: #e5e7eb;
|
||
}
|
||
.embed-preview-page-line.is-short {
|
||
width: 62%;
|
||
}
|
||
.embed-preview-page-banner {
|
||
width: 100%;
|
||
height: 56px;
|
||
border-radius: 6px;
|
||
background: linear-gradient(90deg, #e0e7ff, #ede9fe);
|
||
}
|
||
/* 低层级宿主元素示意:z-index 900(组件层级低于它则被盖住) */
|
||
.embed-preview-chat {
|
||
position: absolute;
|
||
right: 8px;
|
||
bottom: 8px;
|
||
z-index: 900;
|
||
padding: 8px 12px;
|
||
border-radius: 999px;
|
||
background: #10b981;
|
||
color: #fff;
|
||
font-size: 11px;
|
||
box-shadow: 0 2px 8px rgb(0 0 0 / 0.18);
|
||
}
|
||
.embed-preview-badge {
|
||
position: absolute;
|
||
top: 8px;
|
||
right: 8px;
|
||
z-index: 2;
|
||
padding: 2px 8px;
|
||
border-radius: 4px;
|
||
background: #fef3c7;
|
||
border: 1px solid #f59e0b;
|
||
color: #92400e;
|
||
font-size: 10px;
|
||
font-weight: 600;
|
||
letter-spacing: 0.04em;
|
||
}
|
||
.embed-preview-zindex {
|
||
position: absolute;
|
||
top: 8px;
|
||
left: 8px;
|
||
z-index: 2;
|
||
padding: 2px 8px;
|
||
border-radius: 4px;
|
||
background: #e0e7ff;
|
||
border: 1px solid #6366f1;
|
||
color: #3730a3;
|
||
font-size: 10px;
|
||
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
||
}
|
||
.embed-preview-caption {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
color: #6b7280;
|
||
font-size: 12px;
|
||
text-align: center;
|
||
}
|
||
.is-desktop .embed-preview-caption {
|
||
justify-content: center;
|
||
}
|
||
.is-mobile .embed-preview-caption {
|
||
justify-content: center;
|
||
}
|
||
.embed-preview-caption-hint {
|
||
color: #9ca3af;
|
||
}
|
||
|
||
/* ── 悬浮组件本体:镜像 viewer 嵌入页类名(embed-root/head/stage/foot)与
|
||
loader wrapper(圆角 12 + 阴影)——视觉随 viewer 同步,不另起一套 ── */
|
||
.embed-preview-dock {
|
||
display: flex;
|
||
border-radius: 12px;
|
||
box-shadow: 0 4px 16px rgb(0 0 0 / 0.18);
|
||
overflow: hidden;
|
||
}
|
||
/* v2 壳(对齐 loader v2 wrapper:1px #fffc 边、#10161e 底、高 280)。 */
|
||
.embed-preview-dock.is-v2 {
|
||
border: 1px solid #fffc;
|
||
background: #10161e;
|
||
box-shadow: 0 4px 16px #0f172a29;
|
||
height: 280px;
|
||
}
|
||
.embed-preview-v2frame {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
.embed-preview-v2frame iframe {
|
||
width: 100%;
|
||
height: 100%;
|
||
border: 0;
|
||
display: block;
|
||
}
|
||
/* v2 收起把手(对齐 loader v2:白底 100×44、蓝图标)。 */
|
||
.embed-handle--v2 {
|
||
padding: 0;
|
||
width: 100px;
|
||
gap: 8px;
|
||
border: 1px solid #e3eaf2;
|
||
background: #ffffff;
|
||
box-shadow: 0 4px 16px #0f172a20;
|
||
color: #32618e;
|
||
font-size: 12px;
|
||
}
|
||
.embed-preview-sim {
|
||
padding: 2px 10px;
|
||
border: 1px solid #d5dfed;
|
||
border-radius: 6px;
|
||
background: #fff;
|
||
color: #285586;
|
||
font-size: 11px;
|
||
line-height: 20px;
|
||
cursor: pointer;
|
||
}
|
||
.embed-preview-sim:hover {
|
||
background: #f0f6ff;
|
||
}
|
||
.embed-root {
|
||
background: #fff;
|
||
font-family:
|
||
system-ui,
|
||
-apple-system,
|
||
'Segoe UI',
|
||
'PingFang SC',
|
||
sans-serif;
|
||
color: #1f2328;
|
||
}
|
||
.embed-head {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 8px;
|
||
padding: 6px 6px 6px 10px;
|
||
}
|
||
.embed-heading {
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
color: #5e6878;
|
||
letter-spacing: 0.02em;
|
||
}
|
||
.embed-close {
|
||
flex: none;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 28px;
|
||
height: 28px;
|
||
padding: 0;
|
||
border: 0;
|
||
border-radius: 50%;
|
||
background: transparent;
|
||
color: #6b7280;
|
||
cursor: pointer;
|
||
}
|
||
.embed-close:hover {
|
||
background: #f3f4f6;
|
||
color: #374151;
|
||
}
|
||
.embed-stage {
|
||
position: relative;
|
||
aspect-ratio: 4 / 3;
|
||
overflow: hidden;
|
||
background: #1a1a2e; /* 中性深色舞台(viewer EmbedStage 同值) */
|
||
display: flex;
|
||
}
|
||
.embed-stage.is-contain {
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
/* 示例照片 1:1:contain 完整展示(max 约束+居中),cover 铺满裁切 */
|
||
.embed-preview-photo {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: rgb(255 255 255 / 0.85);
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
}
|
||
.is-contain .embed-preview-photo {
|
||
aspect-ratio: 1 / 1;
|
||
max-width: 100%;
|
||
max-height: 100%;
|
||
}
|
||
.is-cover .embed-preview-photo {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
.embed-foot {
|
||
padding: 8px 10px 10px;
|
||
}
|
||
.embed-title {
|
||
margin: 0 0 6px;
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
line-height: 1.3;
|
||
display: -webkit-box;
|
||
-webkit-box-orient: vertical;
|
||
-webkit-line-clamp: 2;
|
||
line-clamp: 2;
|
||
overflow: hidden;
|
||
}
|
||
.embed-foot-row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 8px;
|
||
min-height: 26px;
|
||
}
|
||
.embed-indicator {
|
||
font-size: 12px;
|
||
font-variant-numeric: tabular-nums;
|
||
color: #5e6878;
|
||
white-space: nowrap;
|
||
}
|
||
.embed-foot-actions {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
}
|
||
.embed-foot-btn,
|
||
.embed-foot-link {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-width: 26px;
|
||
height: 26px;
|
||
padding: 0 6px;
|
||
border: 0;
|
||
border-radius: 6px;
|
||
background: transparent;
|
||
color: #1f2937;
|
||
font-size: 12px;
|
||
text-decoration: none;
|
||
}
|
||
.embed-foot-btn:disabled {
|
||
cursor: default;
|
||
opacity: 0.6;
|
||
}
|
||
.embed-foot-link.is-disabled {
|
||
cursor: default;
|
||
opacity: 0.6;
|
||
color: #1f2937;
|
||
}
|
||
/* 收起把手(镜像 loader createHandle:胶囊 44px + 深色底 + 白字) */
|
||
.embed-handle {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 6px;
|
||
height: 44px;
|
||
padding: 0 14px;
|
||
border-radius: 22px;
|
||
background: rgb(15 23 42 / 0.88);
|
||
box-shadow: 0 2px 10px rgb(0 0 0 / 0.3);
|
||
color: #fff;
|
||
font-size: 13px;
|
||
font-weight: 500;
|
||
line-height: 1;
|
||
white-space: nowrap;
|
||
cursor: pointer;
|
||
user-select: none;
|
||
}
|
||
.is-left .embed-handle {
|
||
margin-right: auto;
|
||
}
|
||
.is-right .embed-handle {
|
||
margin-left: auto;
|
||
}
|
||
</style>
|