Video and Image pickers, thumbwheels, aspect icons, and a Scale to MP paddle; extra prompts default to batch so each run starts from the original image. Co-authored-by: Cursor <cursoragent@cursor.com>
177 lines
5.0 KiB
Vue
177 lines
5.0 KiB
Vue
<template>
|
|
<div class="w-[6.5rem] min-w-0">
|
|
<div v-if="label" class="mb-1.5 text-[10px] font-medium uppercase tracking-wider text-zinc-500">{{ label }}</div>
|
|
<button
|
|
type="button"
|
|
role="switch"
|
|
class="lamp-plate relative flex h-[9.75rem] w-full flex-col items-center justify-between overflow-hidden rounded-2xl px-1.5 py-2"
|
|
:class="model ? 'is-on' : 'is-off'"
|
|
:aria-checked="model"
|
|
:aria-label="label || 'Toggle'"
|
|
@click="model = !model"
|
|
>
|
|
<span class="screw tl" aria-hidden="true" />
|
|
<span class="screw tr" aria-hidden="true" />
|
|
<span class="screw bl" aria-hidden="true" />
|
|
<span class="screw br" aria-hidden="true" />
|
|
|
|
<span class="flex flex-col items-center gap-1">
|
|
<span class="led" aria-hidden="true" />
|
|
<span class="stamp" :class="model ? 'stamp-lit' : ''">ON</span>
|
|
</span>
|
|
|
|
<span class="collar" aria-hidden="true">
|
|
<span class="collar-ring" />
|
|
<span class="paddle" :class="model ? 'paddle-on' : 'paddle-off'">
|
|
<span class="paddle-body" />
|
|
</span>
|
|
</span>
|
|
|
|
<span class="stamp" :class="model ? '' : 'stamp-lit'">OFF</span>
|
|
</button>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
defineProps<{
|
|
label?: string
|
|
}>()
|
|
|
|
const model = defineModel<boolean>({ required: true })
|
|
</script>
|
|
|
|
<style scoped>
|
|
.lamp-plate {
|
|
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
background:
|
|
radial-gradient(120% 80% at 50% 0%, rgba(251, 191, 36, 0.08), transparent 55%),
|
|
linear-gradient(180deg, #2a2a2e 0%, #18181b 42%, #0c0c0e 100%);
|
|
box-shadow:
|
|
inset 0 1px 0 rgba(255, 255, 255, 0.12),
|
|
inset 0 -10px 18px rgba(0, 0, 0, 0.45),
|
|
0 8px 18px rgba(0, 0, 0, 0.35);
|
|
}
|
|
.lamp-plate.is-on {
|
|
border-color: rgba(251, 191, 36, 0.45);
|
|
box-shadow:
|
|
inset 0 1px 0 rgba(253, 230, 138, 0.18),
|
|
inset 0 -10px 18px rgba(0, 0, 0, 0.4),
|
|
0 0 18px rgba(251, 191, 36, 0.18);
|
|
}
|
|
.screw {
|
|
position: absolute;
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
background:
|
|
radial-gradient(circle at 35% 30%, #f4f4f5, #a1a1aa 42%, #52525b 70%, #27272a);
|
|
box-shadow:
|
|
0 0 0 0.5px rgba(255, 255, 255, 0.25),
|
|
inset 0 -1px 1px rgba(0, 0, 0, 0.55);
|
|
}
|
|
.screw::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 2px;
|
|
background:
|
|
linear-gradient(#3f3f46, #3f3f46) center / 4px 1px no-repeat,
|
|
linear-gradient(#3f3f46, #3f3f46) center / 1px 4px no-repeat;
|
|
opacity: 0.85;
|
|
}
|
|
.tl { top: 6px; left: 6px; }
|
|
.tr { top: 6px; right: 6px; }
|
|
.bl { bottom: 6px; left: 6px; }
|
|
.br { bottom: 6px; right: 6px; }
|
|
.led {
|
|
width: 10px;
|
|
height: 10px;
|
|
border-radius: 50%;
|
|
background: #3f3f46;
|
|
box-shadow:
|
|
inset 0 1px 2px rgba(0, 0, 0, 0.85),
|
|
0 0 0 1px rgba(0, 0, 0, 0.4);
|
|
}
|
|
.is-on .led {
|
|
background: radial-gradient(circle at 35% 30%, #fef3c7, #fbbf24 55%, #d97706);
|
|
box-shadow:
|
|
0 0 10px rgba(251, 191, 36, 1),
|
|
0 0 18px rgba(251, 191, 36, 0.55),
|
|
inset 0 1px 1px rgba(255, 255, 255, 0.7);
|
|
}
|
|
.stamp {
|
|
font-size: 9px;
|
|
font-weight: 800;
|
|
letter-spacing: 0.18em;
|
|
color: rgba(244, 244, 245, 0.28);
|
|
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.7);
|
|
}
|
|
.stamp-lit {
|
|
color: #fef3c7;
|
|
text-shadow: 0 0 8px rgba(251, 191, 36, 0.7);
|
|
}
|
|
.collar {
|
|
position: relative;
|
|
display: grid;
|
|
place-items: center;
|
|
width: 3.35rem;
|
|
height: 3.35rem;
|
|
}
|
|
.collar-ring {
|
|
position: absolute;
|
|
inset: 0;
|
|
border-radius: 50%;
|
|
background:
|
|
radial-gradient(circle at 30% 26%, #fff 0 5%, transparent 16%),
|
|
repeating-radial-gradient(circle at 50% 50%, #e4e4e7 0 1px, #a1a1aa 2px, #71717a 3px, #3f3f46 4px);
|
|
box-shadow:
|
|
0 3px 6px rgba(0, 0, 0, 0.6),
|
|
inset 0 2px 3px rgba(255, 255, 255, 0.5),
|
|
inset 0 -4px 6px rgba(0, 0, 0, 0.6);
|
|
}
|
|
.collar-ring::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 10px;
|
|
border-radius: 50%;
|
|
background: radial-gradient(circle at 50% 40%, #3f3f46, #09090b 72%);
|
|
box-shadow: inset 0 3px 6px rgba(0, 0, 0, 0.9);
|
|
}
|
|
.paddle {
|
|
position: relative;
|
|
z-index: 1;
|
|
width: 1.15rem;
|
|
height: 2.55rem;
|
|
transform-origin: 50% 50%;
|
|
transition: transform 0.22s cubic-bezier(0.22, 1, 0.36, 1);
|
|
filter: drop-shadow(0 5px 4px rgba(0, 0, 0, 0.55));
|
|
}
|
|
.paddle-on {
|
|
transform: translateY(-0.42rem) rotate(-12deg);
|
|
}
|
|
.paddle-off {
|
|
transform: translateY(0.42rem) rotate(12deg);
|
|
}
|
|
.paddle-body {
|
|
display: block;
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 0.7rem 0.7rem 0.45rem 0.45rem;
|
|
background:
|
|
linear-gradient(180deg, rgba(255, 255, 255, 0.38) 0%, rgba(255, 255, 255, 0.05) 28%, transparent 45%),
|
|
linear-gradient(90deg, #0a0a0b 0%, #3f3f46 46%, #111113 100%);
|
|
box-shadow:
|
|
inset 0 1px 0 rgba(255, 255, 255, 0.4),
|
|
inset 0 -3px 4px rgba(0, 0, 0, 0.7);
|
|
clip-path: polygon(22% 0, 78% 0, 100% 22%, 68% 100%, 32% 100%, 0 22%);
|
|
}
|
|
.is-on .paddle-body {
|
|
background:
|
|
linear-gradient(180deg, rgba(254, 243, 199, 0.7) 0%, rgba(251, 191, 36, 0.2) 26%, transparent 48%),
|
|
linear-gradient(90deg, #1c1408 0%, #b45309 48%, #111 100%);
|
|
box-shadow:
|
|
0 0 10px rgba(251, 191, 36, 0.45),
|
|
inset 0 1px 0 rgba(254, 243, 199, 0.55),
|
|
inset 0 -3px 4px rgba(0, 0, 0, 0.7);
|
|
}
|
|
</style>
|