Add contact option on main pricing page
Docker / build-and-push-image (push) Successful in 1m35s

This commit is contained in:
Jon Staab
2026-06-17 15:03:23 -07:00
parent 7750a5e552
commit 4a5bd4d563
5 changed files with 44 additions and 3 deletions
+1
View File
@@ -28,6 +28,7 @@ pub struct Plan {
pub id: String, pub id: String,
pub name: String, pub name: String,
pub amount: i64, pub amount: i64,
pub hidden: bool,
pub members: Option<i64>, pub members: Option<i64>,
pub blossom: bool, pub blossom: bool,
pub livekit: bool, pub livekit: bool,
+3
View File
@@ -23,6 +23,7 @@ pub fn list_plans() -> Vec<Plan> {
id: "free".to_string(), id: "free".to_string(),
name: "Free".to_string(), name: "Free".to_string(),
amount: 0, amount: 0,
hidden: false,
members: Some(10), members: Some(10),
blossom: false, blossom: false,
livekit: false, livekit: false,
@@ -31,6 +32,7 @@ pub fn list_plans() -> Vec<Plan> {
id: "basic".to_string(), id: "basic".to_string(),
name: "Basic".to_string(), name: "Basic".to_string(),
amount: 500, amount: 500,
hidden: false,
members: Some(100), members: Some(100),
blossom: true, blossom: true,
livekit: true, livekit: true,
@@ -39,6 +41,7 @@ pub fn list_plans() -> Vec<Plan> {
id: "growth".to_string(), id: "growth".to_string(),
name: "Growth".to_string(), name: "Growth".to_string(),
amount: 2500, amount: 2500,
hidden: false,
members: None, members: None,
blossom: true, blossom: true,
livekit: true, livekit: true,
+38 -2
View File
@@ -38,9 +38,24 @@ type PricingTableProps = {
} }
export default function PricingTable(props: PricingTableProps) { export default function PricingTable(props: PricingTableProps) {
// Hidden plans (e.g. the legacy "basic" tier) stay resolvable for billing via
// the backend but never show up in the public pricing table or plan selector.
// This is the only place the hidden flag is honored.
const visiblePlans = () => plans().filter((plan) => !plan.hidden)
// The full pricing page also shows the synthetic "Custom" card, so the column
// count tracks the real number of cards (literal classes so Tailwind keeps them).
const cardCount = () => visiblePlans().length + (props.selectable ? 0 : 1)
const gridCols: Record<number, string> = {
1: "lg:grid-cols-1",
2: "lg:grid-cols-2",
3: "lg:grid-cols-3",
4: "lg:grid-cols-4",
}
return ( return (
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 items-start"> <div class={`grid grid-cols-1 gap-6 items-start ${gridCols[cardCount()] ?? "lg:grid-cols-4"}`}>
<For each={plans()}> <For each={visiblePlans()}>
{(plan) => { {(plan) => {
const isPopular = plan.id === "basic" const isPopular = plan.id === "basic"
const isSelected = () => props.selectable && props.selectedPlanId === plan.id const isSelected = () => props.selectable && props.selectedPlanId === plan.id
@@ -99,6 +114,27 @@ export default function PricingTable(props: PricingTableProps) {
) )
}} }}
</For> </For>
{!props.selectable && (
<div class="relative bg-white rounded-2xl p-8 border border-gray-200">
<h3 class="text-lg font-bold text-gray-900 mb-1">Custom</h3>
<div class="mb-8">
<span class="text-4xl font-extrabold text-gray-900">Let's talk</span>
</div>
<ul class="mb-8 text-sm text-gray-600 space-y-3">
<li class="flex items-start gap-2"><CheckIcon />White-labeled app</li>
<li class="flex items-start gap-2"><CheckIcon />Dedicated support</li>
<li class="flex items-start gap-2"><CheckIcon />Custom feature development</li>
</ul>
<a
href="https://cal.com/coracle.social/30min"
target="_blank"
rel="noopener noreferrer"
class="block w-full text-center py-2.5 px-4 text-sm rounded-xl font-semibold transition-colors border border-gray-200 text-gray-700 hover:bg-gray-50"
>
Contact us
</a>
</div>
)}
</div> </div>
) )
} }
+1 -1
View File
@@ -113,7 +113,7 @@ export default function RelayForm(props: RelayFormProps) {
<div> <div>
<label class="block text-sm font-medium text-gray-700 mb-3">Plan</label> <label class="block text-sm font-medium text-gray-700 mb-3">Plan</label>
<div class="grid grid-cols-3 gap-3"> <div class="grid grid-cols-3 gap-3">
<For each={plans()}> <For each={plans().filter((p) => !p.hidden)}>
{(p) => ( {(p) => (
<button <button
type="button" type="button"
+1
View File
@@ -35,6 +35,7 @@ export type Plan = {
id: string id: string
name: string name: string
amount: number amount: number
hidden: boolean
members: number | null members: number | null
blossom: boolean blossom: boolean
livekit: boolean livekit: boolean