feat: transition improvements
parent
64edbb6b82
commit
ccac97c7c4
|
|
@ -44,7 +44,7 @@ export const defaultConfig: LightRaysConfig = {
|
|||
saturation: 0.325,
|
||||
followMouse: false,
|
||||
mouseInfluence: 0.05,
|
||||
noiseAmount: 0.25,
|
||||
noiseAmount: 0.5,
|
||||
distortion: 0.0,
|
||||
opacity: 0.35,
|
||||
}
|
||||
|
|
@ -107,136 +107,136 @@ interface UniformData {
|
|||
}
|
||||
|
||||
const WGSL_SHADER = `
|
||||
struct Uniforms {
|
||||
iTime: f32,
|
||||
_pad0: f32,
|
||||
iResolution: vec2<f32>,
|
||||
rayPos: vec2<f32>,
|
||||
rayDir: vec2<f32>,
|
||||
raysColor: vec3<f32>,
|
||||
raysSpeed: f32,
|
||||
lightSpread: f32,
|
||||
rayLength: f32,
|
||||
sourceWidth: f32,
|
||||
pulsating: f32,
|
||||
pulsatingMin: f32,
|
||||
pulsatingMax: f32,
|
||||
fadeDistance: f32,
|
||||
saturation: f32,
|
||||
mousePos: vec2<f32>,
|
||||
mouseInfluence: f32,
|
||||
noiseAmount: f32,
|
||||
distortion: f32,
|
||||
_pad1: f32,
|
||||
_pad2: f32,
|
||||
_pad3: f32,
|
||||
};
|
||||
struct Uniforms {
|
||||
iTime: f32,
|
||||
_pad0: f32,
|
||||
iResolution: vec2<f32>,
|
||||
rayPos: vec2<f32>,
|
||||
rayDir: vec2<f32>,
|
||||
raysColor: vec3<f32>,
|
||||
raysSpeed: f32,
|
||||
lightSpread: f32,
|
||||
rayLength: f32,
|
||||
sourceWidth: f32,
|
||||
pulsating: f32,
|
||||
pulsatingMin: f32,
|
||||
pulsatingMax: f32,
|
||||
fadeDistance: f32,
|
||||
saturation: f32,
|
||||
mousePos: vec2<f32>,
|
||||
mouseInfluence: f32,
|
||||
noiseAmount: f32,
|
||||
distortion: f32,
|
||||
_pad1: f32,
|
||||
_pad2: f32,
|
||||
_pad3: f32,
|
||||
};
|
||||
|
||||
@group(0) @binding(0) var<uniform> uniforms: Uniforms;
|
||||
@group(0) @binding(0) var<uniform> uniforms: Uniforms;
|
||||
|
||||
struct VertexOutput {
|
||||
@builtin(position) position: vec4<f32>,
|
||||
@location(0) vUv: vec2<f32>,
|
||||
};
|
||||
struct VertexOutput {
|
||||
@builtin(position) position: vec4<f32>,
|
||||
@location(0) vUv: vec2<f32>,
|
||||
};
|
||||
|
||||
@vertex
|
||||
fn vertexMain(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
|
||||
// Full-screen triangle
|
||||
var positions = array<vec2<f32>, 3>(
|
||||
vec2<f32>(-1.0, -1.0),
|
||||
vec2<f32>(3.0, -1.0),
|
||||
vec2<f32>(-1.0, 3.0)
|
||||
);
|
||||
|
||||
var output: VertexOutput;
|
||||
let pos = positions[vertexIndex];
|
||||
output.position = vec4<f32>(pos, 0.0, 1.0);
|
||||
output.vUv = pos * 0.5 + 0.5;
|
||||
return output;
|
||||
}
|
||||
|
||||
fn noise(st: vec2<f32>) -> f32 {
|
||||
return fract(sin(dot(st, vec2<f32>(12.9898, 78.233))) * 43758.5453123);
|
||||
}
|
||||
|
||||
fn rayStrength(raySource: vec2<f32>, rayRefDirection: vec2<f32>, coord: vec2<f32>,
|
||||
seedA: f32, seedB: f32, speed: f32) -> f32 {
|
||||
let sourceToCoord = coord - raySource;
|
||||
let dirNorm = normalize(sourceToCoord);
|
||||
let cosAngle = dot(dirNorm, rayRefDirection);
|
||||
|
||||
let distortedAngle = cosAngle + uniforms.distortion * sin(uniforms.iTime * 2.0 + length(sourceToCoord) * 0.01) * 0.2;
|
||||
|
||||
let spreadFactor = pow(max(distortedAngle, 0.0), 1.0 / max(uniforms.lightSpread, 0.001));
|
||||
|
||||
let distance = length(sourceToCoord);
|
||||
let maxDistance = uniforms.iResolution.x * uniforms.rayLength;
|
||||
let lengthFalloff = clamp((maxDistance - distance) / maxDistance, 0.0, 1.0);
|
||||
|
||||
let fadeFalloff = clamp((uniforms.iResolution.x * uniforms.fadeDistance - distance) / (uniforms.iResolution.x * uniforms.fadeDistance), 0.5, 1.0);
|
||||
let pulseCenter = (uniforms.pulsatingMin + uniforms.pulsatingMax) * 0.5;
|
||||
let pulseAmplitude = (uniforms.pulsatingMax - uniforms.pulsatingMin) * 0.5;
|
||||
var pulse: f32;
|
||||
if (uniforms.pulsating > 0.5) {
|
||||
pulse = pulseCenter + pulseAmplitude * sin(uniforms.iTime * speed * 3.0);
|
||||
} else {
|
||||
pulse = 1.0;
|
||||
@vertex
|
||||
fn vertexMain(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
|
||||
// Full-screen triangle
|
||||
var positions = array<vec2<f32>, 3>(
|
||||
vec2<f32>(-1.0, -1.0),
|
||||
vec2<f32>(3.0, -1.0),
|
||||
vec2<f32>(-1.0, 3.0)
|
||||
);
|
||||
|
||||
var output: VertexOutput;
|
||||
let pos = positions[vertexIndex];
|
||||
output.position = vec4<f32>(pos, 0.0, 1.0);
|
||||
output.vUv = pos * 0.5 + 0.5;
|
||||
return output;
|
||||
}
|
||||
|
||||
let baseStrength = clamp(
|
||||
(0.45 + 0.15 * sin(distortedAngle * seedA + uniforms.iTime * speed)) +
|
||||
(0.3 + 0.2 * cos(-distortedAngle * seedB + uniforms.iTime * speed)),
|
||||
0.0, 1.0
|
||||
);
|
||||
|
||||
return baseStrength * lengthFalloff * fadeFalloff * spreadFactor * pulse;
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fragmentMain(@builtin(position) fragCoord: vec4<f32>, @location(0) vUv: vec2<f32>) -> @location(0) vec4<f32> {
|
||||
let coord = vec2<f32>(fragCoord.x, fragCoord.y);
|
||||
|
||||
let normalizedX = (coord.x / uniforms.iResolution.x) - 0.5;
|
||||
let widthOffset = -normalizedX * uniforms.sourceWidth * uniforms.iResolution.x;
|
||||
|
||||
let perpDir = vec2<f32>(-uniforms.rayDir.y, uniforms.rayDir.x);
|
||||
let adjustedRayPos = uniforms.rayPos + perpDir * widthOffset;
|
||||
|
||||
var finalRayDir = uniforms.rayDir;
|
||||
if (uniforms.mouseInfluence > 0.0) {
|
||||
let mouseScreenPos = uniforms.mousePos * uniforms.iResolution;
|
||||
let mouseDirection = normalize(mouseScreenPos - adjustedRayPos);
|
||||
finalRayDir = normalize(mix(uniforms.rayDir, mouseDirection, uniforms.mouseInfluence));
|
||||
fn noise(st: vec2<f32>) -> f32 {
|
||||
return fract(sin(dot(st, vec2<f32>(12.9898, 78.233))) * 43758.5453123);
|
||||
}
|
||||
|
||||
let rays1 = vec4<f32>(1.0) *
|
||||
rayStrength(adjustedRayPos, finalRayDir, coord, 36.2214, 21.11349,
|
||||
1.5 * uniforms.raysSpeed);
|
||||
let rays2 = vec4<f32>(1.0) *
|
||||
rayStrength(adjustedRayPos, finalRayDir, coord, 22.3991, 18.0234,
|
||||
1.1 * uniforms.raysSpeed);
|
||||
fn rayStrength(raySource: vec2<f32>, rayRefDirection: vec2<f32>, coord: vec2<f32>,
|
||||
seedA: f32, seedB: f32, speed: f32) -> f32 {
|
||||
let sourceToCoord = coord - raySource;
|
||||
let dirNorm = normalize(sourceToCoord);
|
||||
let cosAngle = dot(dirNorm, rayRefDirection);
|
||||
|
||||
var fragColor = rays1 * 0.5 + rays2 * 0.4;
|
||||
let distortedAngle = cosAngle + uniforms.distortion * sin(uniforms.iTime * 2.0 + length(sourceToCoord) * 0.01) * 0.2;
|
||||
|
||||
let spreadFactor = pow(max(distortedAngle, 0.0), 1.0 / max(uniforms.lightSpread, 0.001));
|
||||
|
||||
if (uniforms.noiseAmount > 0.0) {
|
||||
let n = noise(coord * 0.01 + uniforms.iTime * 0.1);
|
||||
fragColor = vec4<f32>(fragColor.rgb * (1.0 - uniforms.noiseAmount + uniforms.noiseAmount * n), fragColor.a);
|
||||
let distance = length(sourceToCoord);
|
||||
let maxDistance = uniforms.iResolution.x * uniforms.rayLength;
|
||||
let lengthFalloff = clamp((maxDistance - distance) / maxDistance, 0.0, 1.0);
|
||||
|
||||
let fadeFalloff = clamp((uniforms.iResolution.x * uniforms.fadeDistance - distance) / (uniforms.iResolution.x * uniforms.fadeDistance), 0.5, 1.0);
|
||||
let pulseCenter = (uniforms.pulsatingMin + uniforms.pulsatingMax) * 0.5;
|
||||
let pulseAmplitude = (uniforms.pulsatingMax - uniforms.pulsatingMin) * 0.5;
|
||||
var pulse: f32;
|
||||
if (uniforms.pulsating > 0.5) {
|
||||
pulse = pulseCenter + pulseAmplitude * sin(uniforms.iTime * speed * 3.0);
|
||||
} else {
|
||||
pulse = 1.0;
|
||||
}
|
||||
|
||||
let baseStrength = clamp(
|
||||
(0.45 + 0.15 * sin(distortedAngle * seedA + uniforms.iTime * speed)) +
|
||||
(0.3 + 0.2 * cos(-distortedAngle * seedB + uniforms.iTime * speed)),
|
||||
0.0, 1.0
|
||||
);
|
||||
|
||||
return baseStrength * lengthFalloff * fadeFalloff * spreadFactor * pulse;
|
||||
}
|
||||
|
||||
let brightness = 1.0 - (coord.y / uniforms.iResolution.y);
|
||||
fragColor.x = fragColor.x * (0.1 + brightness * 0.8);
|
||||
fragColor.y = fragColor.y * (0.3 + brightness * 0.6);
|
||||
fragColor.z = fragColor.z * (0.5 + brightness * 0.5);
|
||||
@fragment
|
||||
fn fragmentMain(@builtin(position) fragCoord: vec4<f32>, @location(0) vUv: vec2<f32>) -> @location(0) vec4<f32> {
|
||||
let coord = vec2<f32>(fragCoord.x, fragCoord.y);
|
||||
|
||||
let normalizedX = (coord.x / uniforms.iResolution.x) - 0.5;
|
||||
let widthOffset = -normalizedX * uniforms.sourceWidth * uniforms.iResolution.x;
|
||||
|
||||
let perpDir = vec2<f32>(-uniforms.rayDir.y, uniforms.rayDir.x);
|
||||
let adjustedRayPos = uniforms.rayPos + perpDir * widthOffset;
|
||||
|
||||
var finalRayDir = uniforms.rayDir;
|
||||
if (uniforms.mouseInfluence > 0.0) {
|
||||
let mouseScreenPos = uniforms.mousePos * uniforms.iResolution;
|
||||
let mouseDirection = normalize(mouseScreenPos - adjustedRayPos);
|
||||
finalRayDir = normalize(mix(uniforms.rayDir, mouseDirection, uniforms.mouseInfluence));
|
||||
}
|
||||
|
||||
if (uniforms.saturation != 1.0) {
|
||||
let gray = dot(fragColor.rgb, vec3<f32>(0.299, 0.587, 0.114));
|
||||
fragColor = vec4<f32>(mix(vec3<f32>(gray), fragColor.rgb, uniforms.saturation), fragColor.a);
|
||||
let rays1 = vec4<f32>(1.0) *
|
||||
rayStrength(adjustedRayPos, finalRayDir, coord, 36.2214, 21.11349,
|
||||
1.5 * uniforms.raysSpeed);
|
||||
let rays2 = vec4<f32>(1.0) *
|
||||
rayStrength(adjustedRayPos, finalRayDir, coord, 22.3991, 18.0234,
|
||||
1.1 * uniforms.raysSpeed);
|
||||
|
||||
var fragColor = rays1 * 0.5 + rays2 * 0.4;
|
||||
|
||||
if (uniforms.noiseAmount > 0.0) {
|
||||
let n = noise(coord * 0.01 + uniforms.iTime * 0.1);
|
||||
fragColor = vec4<f32>(fragColor.rgb * (1.0 - uniforms.noiseAmount + uniforms.noiseAmount * n), fragColor.a);
|
||||
}
|
||||
|
||||
let brightness = 1.0 - (coord.y / uniforms.iResolution.y);
|
||||
fragColor.x = fragColor.x * (0.1 + brightness * 0.8);
|
||||
fragColor.y = fragColor.y * (0.3 + brightness * 0.6);
|
||||
fragColor.z = fragColor.z * (0.5 + brightness * 0.5);
|
||||
|
||||
if (uniforms.saturation != 1.0) {
|
||||
let gray = dot(fragColor.rgb, vec3<f32>(0.299, 0.587, 0.114));
|
||||
fragColor = vec4<f32>(mix(vec3<f32>(gray), fragColor.rgb, uniforms.saturation), fragColor.a);
|
||||
}
|
||||
|
||||
fragColor = vec4<f32>(fragColor.rgb * uniforms.raysColor, fragColor.a);
|
||||
|
||||
return fragColor;
|
||||
}
|
||||
|
||||
fragColor = vec4<f32>(fragColor.rgb * uniforms.raysColor, fragColor.a);
|
||||
|
||||
return fragColor;
|
||||
}
|
||||
`
|
||||
|
||||
const UNIFORM_BUFFER_SIZE = 96
|
||||
|
|
|
|||
|
|
@ -14,13 +14,14 @@ export const github = query(async () => {
|
|||
fetch(`${apiBaseUrl}/releases`, { headers }).then((res) => res.json()),
|
||||
fetch(`${apiBaseUrl}/contributors?per_page=1`, { headers }),
|
||||
])
|
||||
if (!Array.isArray(releases) || releases.length === 0) {
|
||||
return undefined
|
||||
}
|
||||
const [release] = releases
|
||||
const contributorCount = Number.parseInt(
|
||||
contributors.headers
|
||||
.get("Link")!
|
||||
.match(/&page=(\d+)>; rel="last"/)!
|
||||
.at(1)!,
|
||||
)
|
||||
const linkHeader = contributors.headers.get("Link")
|
||||
const contributorCount = linkHeader
|
||||
? Number.parseInt(linkHeader.match(/&page=(\d+)>; rel="last"/)?.at(1) ?? "0")
|
||||
: 0
|
||||
return {
|
||||
stars: meta.stargazers_count,
|
||||
release: {
|
||||
|
|
|
|||
|
|
@ -1,44 +1,34 @@
|
|||
::view-transition-group(*) {
|
||||
animation-duration: 200ms;
|
||||
animation-timing-function: cubic-bezier(0.25, 0, 0.5, 1);
|
||||
animation-duration: 250ms;
|
||||
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
::view-transition-old(root),
|
||||
::view-transition-new(root) {
|
||||
animation-duration: 200ms;
|
||||
animation-timing-function: cubic-bezier(0.25, 0, 0.5, 1);
|
||||
animation-duration: 250ms;
|
||||
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
@keyframes reveal {
|
||||
from {
|
||||
mask-position: 0% 200%;
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
mask-position: 0% 50%;
|
||||
opacity: 1;
|
||||
}
|
||||
::view-transition-image-pair(root) {
|
||||
isolation: isolate;
|
||||
}
|
||||
|
||||
@keyframes reveal-reverse {
|
||||
from {
|
||||
mask-position: 0% 50%;
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
mask-position: 0% 200%;
|
||||
opacity: 0;
|
||||
}
|
||||
::view-transition-old(root) {
|
||||
animation: none;
|
||||
mix-blend-mode: normal;
|
||||
}
|
||||
|
||||
::view-transition-new(root) {
|
||||
animation: none;
|
||||
mix-blend-mode: normal;
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(4px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -51,20 +41,93 @@
|
|||
}
|
||||
}
|
||||
|
||||
::view-transition-new(terms) {
|
||||
animation: reveal 400ms cubic-bezier(0.25, 0, 0.5, 1) forwards;
|
||||
@keyframes fade-in-up {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
::view-transition-old(terms) {
|
||||
animation: reveal-reverse 200ms cubic-bezier(0.25, 0, 0.5, 1) forwards;
|
||||
@keyframes reveal-terms {
|
||||
from {
|
||||
mask-position: 0% 200%;
|
||||
}
|
||||
to {
|
||||
mask-position: 0% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
::view-transition-new(action) {
|
||||
animation: fade-in 300ms cubic-bezier(0.25, 0, 0.5, 1) forwards;
|
||||
@keyframes hide-terms {
|
||||
from {
|
||||
mask-position: 0% 50%;
|
||||
}
|
||||
to {
|
||||
mask-position: 0% 200%;
|
||||
}
|
||||
}
|
||||
|
||||
::view-transition-old(action) {
|
||||
animation: fade-out 150ms cubic-bezier(0.25, 0, 0.5, 1) forwards;
|
||||
::view-transition-old(terms-20),
|
||||
::view-transition-old(terms-100),
|
||||
::view-transition-old(terms-200) {
|
||||
mask-image: linear-gradient(to bottom, transparent, black 25% 75%, transparent);
|
||||
mask-repeat: no-repeat;
|
||||
mask-size: 100% 200%;
|
||||
animation: hide-terms 200ms cubic-bezier(0.25, 0, 0.5, 1) forwards;
|
||||
}
|
||||
|
||||
::view-transition-new(terms-20),
|
||||
::view-transition-new(terms-100),
|
||||
::view-transition-new(terms-200) {
|
||||
mask-image: linear-gradient(to bottom, transparent, black 25% 75%, transparent);
|
||||
mask-repeat: no-repeat;
|
||||
mask-position: 0% 200%;
|
||||
mask-size: 100% 200%;
|
||||
animation: reveal-terms 300ms cubic-bezier(0.25, 0, 0.5, 1) 50ms forwards;
|
||||
}
|
||||
|
||||
::view-transition-old(action-20),
|
||||
::view-transition-old(action-100),
|
||||
::view-transition-old(action-200) {
|
||||
animation: fade-out 100ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
|
||||
}
|
||||
|
||||
::view-transition-new(action-20),
|
||||
::view-transition-new(action-100),
|
||||
::view-transition-new(action-200) {
|
||||
animation: fade-in-up 200ms cubic-bezier(0.16, 1, 0.3, 1) 250ms forwards;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
::view-transition-group(plan-card-20),
|
||||
::view-transition-group(plan-card-100),
|
||||
::view-transition-group(plan-card-200) {
|
||||
animation-duration: 200ms;
|
||||
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
::view-transition-image-pair(plan-card-20),
|
||||
::view-transition-image-pair(plan-card-100),
|
||||
::view-transition-image-pair(plan-card-200) {
|
||||
isolation: isolate;
|
||||
}
|
||||
|
||||
::view-transition-old(plan-card-20),
|
||||
::view-transition-old(plan-card-100),
|
||||
::view-transition-old(plan-card-200) {
|
||||
animation: fade-out 120ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
|
||||
mix-blend-mode: normal;
|
||||
}
|
||||
|
||||
::view-transition-new(plan-card-20),
|
||||
::view-transition-new(plan-card-100),
|
||||
::view-transition-new(plan-card-200) {
|
||||
animation: fade-in 150ms cubic-bezier(0.4, 0, 0.2, 1) 50ms forwards;
|
||||
opacity: 0;
|
||||
mix-blend-mode: normal;
|
||||
}
|
||||
|
||||
[data-page="black"] {
|
||||
|
|
@ -285,15 +348,15 @@
|
|||
gap: 12px;
|
||||
padding: 24px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.17);
|
||||
background: rgba(0, 0, 0, 0.75);
|
||||
backdrop-filter: blur(10px);
|
||||
background: black;
|
||||
background-clip: padding-box;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
transition: border-color 0.15s ease;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
|
||||
&:hover {
|
||||
&:hover:not(:active) {
|
||||
border-color: rgba(255, 255, 255, 0.35);
|
||||
}
|
||||
|
||||
|
|
@ -388,10 +451,6 @@
|
|||
flex-direction: column;
|
||||
gap: 8px;
|
||||
text-align: left;
|
||||
mask-image: linear-gradient(to bottom, transparent, black 25% 75%, transparent);
|
||||
mask-repeat: no-repeat;
|
||||
mask-position: 0% 50%;
|
||||
mask-size: 100% 200%;
|
||||
|
||||
li {
|
||||
color: rgba(255, 255, 255, 0.59);
|
||||
|
|
|
|||
|
|
@ -47,12 +47,12 @@ export default function Black() {
|
|||
type="button"
|
||||
onClick={() => select(plan.id)}
|
||||
data-slot="pricing-card"
|
||||
style={{ "view-transition-name": `plan-card-${plan.id}` }}
|
||||
style={{ "view-transition-name": `card-${plan.id}` }}
|
||||
>
|
||||
<div data-slot="icon" style={{ "view-transition-name": `plan-icon-${plan.id}` }}>
|
||||
<PlanIcon plan={plan.id} />{" "}
|
||||
<div data-slot="icon" style={{ "view-transition-name": `icon-${plan.id}` }}>
|
||||
<PlanIcon plan={plan.id} />
|
||||
</div>
|
||||
<p data-slot="price" style={{ "view-transition-name": `plan-price-${plan.id}` }}>
|
||||
<p data-slot="price" style={{ "view-transition-name": `price-${plan.id}` }}>
|
||||
<span data-slot="amount">${plan.id}</span> <span data-slot="period">per month</span>
|
||||
<Show when={plan.multiplier}>
|
||||
<span data-slot="multiplier">{plan.multiplier}</span>
|
||||
|
|
@ -66,18 +66,18 @@ export default function Black() {
|
|||
<Match when={selectedPlan()}>
|
||||
{(plan) => (
|
||||
<div data-slot="selected-plan">
|
||||
<div data-slot="selected-card" style={{ "view-transition-name": `plan-card-${plan().id}` }}>
|
||||
<div data-slot="icon" style={{ "view-transition-name": `plan-icon-${plan().id}` }}>
|
||||
<div data-slot="selected-card" style={{ "view-transition-name": `card-${plan().id}` }}>
|
||||
<div data-slot="icon" style={{ "view-transition-name": `icon-${plan().id}` }}>
|
||||
<PlanIcon plan={plan().id} />
|
||||
</div>
|
||||
<p data-slot="price" style={{ "view-transition-name": `plan-price-${plan().id}` }}>
|
||||
<p data-slot="price" style={{ "view-transition-name": `price-${plan().id}` }}>
|
||||
<span data-slot="amount">${plan().id}</span>{" "}
|
||||
<span data-slot="period">per person billed monthly</span>
|
||||
<Show when={plan().multiplier}>
|
||||
<span data-slot="multiplier">{plan().multiplier}</span>
|
||||
</Show>
|
||||
</p>
|
||||
<ul data-slot="terms" style={{ "view-transition-name": "terms" }}>
|
||||
<ul data-slot="terms" style={{ "view-transition-name": `terms-${plan().id}` }}>
|
||||
<li>Your subscription will not start immediately</li>
|
||||
<li>You will be added to the waitlist and activated soon</li>
|
||||
<li>Your card will be only charged when your subscription is activated</li>
|
||||
|
|
@ -86,7 +86,77 @@ export default function Black() {
|
|||
<li>Limits may be adjusted and plans may be discontinued in the future</li>
|
||||
<li>Cancel your subscription at anytime</li>
|
||||
</ul>
|
||||
<div data-slot="actions" style={{ "view-transition-name": "action" }}>
|
||||
<div data-slot="actions" style={{ "view-transition-name": `actions-${plan().id}` }}>
|
||||
<button type="button" onClick={() => cancel()} data-slot="cancel">
|
||||
Cancel
|
||||
</button>
|
||||
<a href={`/black/subscribe/${plan().id}`} data-slot="continue">
|
||||
Continue
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Match>
|
||||
<Match when={selectedPlan()}>
|
||||
{(plan) => (
|
||||
<div data-slot="selected-plan">
|
||||
<div data-slot="selected-card">
|
||||
<div data-slot="icon" style={{ "view-transition-name": `icon-${plan().id}` }}>
|
||||
<PlanIcon plan={plan().id} />
|
||||
</div>
|
||||
<p data-slot="price" style={{ "view-transition-name": `price-${plan().id}` }}>
|
||||
<span data-slot="amount">${plan().id}</span>{" "}
|
||||
<span data-slot="period">per person billed monthly</span>
|
||||
<Show when={plan().multiplier}>
|
||||
<span data-slot="multiplier">{plan().multiplier}</span>
|
||||
</Show>
|
||||
</p>
|
||||
<ul data-slot="terms" style={{ "view-transition-name": `terms-${plan().id}` }}>
|
||||
<li>Your subscription will not start immediately</li>
|
||||
<li>You will be added to the waitlist and activated soon</li>
|
||||
<li>Your card will be only charged when your subscription is activated</li>
|
||||
<li>Usage limits apply, heavily automated use may reach limits sooner</li>
|
||||
<li>Subscriptions for individuals, contact Enterprise for teams</li>
|
||||
<li>Limits may be adjusted and plans may be discontinued in the future</li>
|
||||
<li>Cancel your subscription at anytime</li>
|
||||
</ul>
|
||||
<div data-slot="actions" style={{ "view-transition-name": `actions-${plan().id}` }}>
|
||||
<button type="button" onClick={() => cancel()} data-slot="cancel">
|
||||
Cancel
|
||||
</button>
|
||||
<a href={`/black/subscribe/${plan().id}`} data-slot="continue">
|
||||
Continue
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Match>
|
||||
<Match when={selectedPlan()}>
|
||||
{(plan) => (
|
||||
<div data-slot="selected-plan" style={{ "view-transition-name": "selected-plan" }}>
|
||||
<div data-slot="selected-card">
|
||||
<div data-slot="icon">
|
||||
<PlanIcon plan={plan().id} />
|
||||
</div>
|
||||
<p data-slot="price">
|
||||
<span data-slot="amount">${plan().id}</span>{" "}
|
||||
<span data-slot="period">per person billed monthly</span>
|
||||
<Show when={plan().multiplier}>
|
||||
<span data-slot="multiplier">{plan().multiplier}</span>
|
||||
</Show>
|
||||
</p>
|
||||
<ul data-slot="terms" style={{ "view-transition-name": `terms-${plan().id}` }}>
|
||||
<li>Your subscription will not start immediately</li>
|
||||
<li>You will be added to the waitlist and activated soon</li>
|
||||
<li>Your card will be only charged when your subscription is activated</li>
|
||||
<li>Usage limits apply, heavily automated use may reach limits sooner</li>
|
||||
<li>Subscriptions for individuals, contact Enterprise for teams</li>
|
||||
<li>Limits may be adjusted and plans may be discontinued in the future</li>
|
||||
<li>Cancel your subscription at anytime</li>
|
||||
</ul>
|
||||
<div data-slot="actions" style={{ "view-transition-name": `actions-${plan().id}` }}>
|
||||
<button type="button" onClick={() => cancel()} data-slot="cancel">
|
||||
Cancel
|
||||
</button>
|
||||
|
|
|
|||
Loading…
Reference in New Issue