diff --git a/info/pricing.mdx b/info/pricing.mdx index 68817603..a3c551ff 100644 --- a/info/pricing.mdx +++ b/info/pricing.mdx @@ -53,3 +53,9 @@ With Browser Pools, you pay the standard usage-based price per GB-second while b | Managed auth profiles | N/A | 3 | 20 | Custom | > Note: Limits are org-wide by default unless stated otherwise. `Managed auth profiles` refer to the number of active auth profiles that Kernel maintains using your stored [Credentials](/auth/credentials) or [1Password connection](/integrations/1password). + +## Pricing calculator + +import { PricingCalculator } from '/snippets/calculator.jsx'; + + diff --git a/snippets/calculator.jsx b/snippets/calculator.jsx new file mode 100644 index 00000000..14e15a38 --- /dev/null +++ b/snippets/calculator.jsx @@ -0,0 +1,93 @@ +import { useState, useEffect, useRef } from 'react'; +import { Card, Columns } from '@mintlify/components'; + +export const PricingCalculator = () => { + const planPrices = { + free: 0, + hobbyist: 30, + startup: 200, + } + const usagePrices = 0.0000166667 + + const [plan, setPlan] = useState('free'); + const [headless, setHeadless] = useState(true); + const [avgSessionLength, setAvgSessionLength] = useState(30); + const [numSessions, setNumSessions] = useState(100); + const [flash, setFlash] = useState(false); + const prevPriceRef = useRef(null); + + let price = planPrices[plan]; + let usageCost = 0 + if (headless) { + usageCost += usagePrices * 1 * numSessions * avgSessionLength; + } else { + usageCost += usagePrices * 8 * numSessions * avgSessionLength; + } + + let includedUsageCredits = 5; + if (plan === 'hobbyist') { + includedUsageCredits = 10; + } else if (plan === 'startup') { + includedUsageCredits = 50; + } + if (usageCost > includedUsageCredits) { + price += Math.max(0, usageCost - includedUsageCredits); + } + useEffect(() => { + const prev = prevPriceRef.current; + if (prev !== null && (prev.usageCost !== usageCost || prev.includedUsageCredits !== includedUsageCredits || prev.price !== price)) { + setFlash(true); + const t = setTimeout(() => setFlash(false), 300); + return () => clearTimeout(t); + } + prevPriceRef.current = { usageCost, includedUsageCredits, price }; + }, [usageCost, includedUsageCredits, price]); + const labelStyle = { fontWeight: 600, fontSize: '0.875rem', minWidth: '10rem', flexShrink: 0, maxWidth: '10rem' }; + const rowStyle = { display: 'flex', alignItems: 'center', gap: '0.5rem', minHeight: '2.25rem' }; + const inputStyle = { minWidth: 0, flex: 1, maxWidth: '100%', boxSizing: 'border-box', background: 'transparent' }; + const numberInputStyle = { + borderBottom: '1px solid #7c3aed', textAlign: 'right' + }; + const selectStyle = { + ...inputStyle, + appearance: 'none', + backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%23374151'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'/%3E%3C/svg%3E")`, + backgroundRepeat: 'no-repeat', + backgroundPosition: 'right 0.5rem center', + backgroundSize: '0.75rem', + paddingRight: '1.5rem', + }; + return ( + + + + Plan + setPlan(e.target.value)}> + Free + Hobbyist + Startup + + + + Session length (seconds) + setAvgSessionLength(parseInt(e.target.value))} /> + + + Number of sessions + setNumSessions(parseInt(e.target.value))} /> + + + setHeadless(false)}>Headful + setHeadless(true)}>Headless + + ${headless ? usagePrices.toFixed(8) : (usagePrices * 8).toFixed(8)}/second + + + Base plan: ${planPrices[plan].toFixed(2)} + Usage: +${usageCost.toFixed(2)} + Free credits: -${includedUsageCredits.toFixed(2)} + Total cost: ${price.toFixed(2)} + + + ); +}; \ No newline at end of file diff --git a/style.css b/style.css index c14456ed..ad733458 100644 --- a/style.css +++ b/style.css @@ -1,3 +1,13 @@ +/* pricing calculator button styling */ +:root { + --btn-selected-bg: rgb(224 209 254); + --btn-border: #000; +} +:is(.dark) { + --btn-selected-bg: rgb(124, 58, 237); + --btn-border: #fff; +} + /* style sidebar titles */ #navigation-items .sidebar-group-header #sidebar-title{ font-weight: bold;