diff --git a/resources/css/app.css b/resources/css/app.css index 7f7758a..352d534 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -85,6 +85,14 @@ * which also meant the dark rule sat ~13% heavier than its light counterpart * for no reason. Dark is 0.08 here so the two match optically. */ + /* + * One step off the base ground. Serves both the raised section tone and any + * inset panel — a code block, a segmented-control track — because those are + * the same visual idea seen from opposite sides, and they were previously + * five different raw alpha pairs. + */ + --color-surface-raised: var(--surface-raised); + --color-rule: var(--rule); --color-rule-strong: var(--rule-strong); @@ -303,6 +311,18 @@ html { * its own reduced-motion branch rather than relying on this block. */ +/* + * The accent tint scale, recorded because it was seven values in two syntaxes. + * + * /5 a surface marked as the featured one — the Starter card, the TablePro + * column in either comparison table + * /10 a filled chip or step marker, and the selected state of a control + * + * `safety.tsx` keeps its own /[0.02] /[0.04] /[0.06] ladder. That is not drift: + * the tint there encodes how far up the six-level ladder a row sits, so the + * steps have to be finer than the scale above and have to be evenly spaced. + */ + /* * Row selection, borrowed from the product's own grid. * diff --git a/resources/js/components/landing/agents-mcp.tsx b/resources/js/components/landing/agents-mcp.tsx index 104d315..8dc35f0 100644 --- a/resources/js/components/landing/agents-mcp.tsx +++ b/resources/js/components/landing/agents-mcp.tsx @@ -1,6 +1,7 @@ import { useEffect, useRef, useState } from 'react'; import { Check, Copy } from 'lucide-react'; import { toast } from 'sonner'; +import { CodeBlock } from '@/components/ui/code'; import Container from '@/components/ui/container'; import { FullLine } from '@/components/ui/full-line'; import { Ledger, LedgerRow } from '@/components/ui/ledger'; @@ -141,7 +142,8 @@ export default function AgentsMcp() { -
+                        
+                            
                             
                                 {'{'}
                                 {'\n'}
@@ -168,7 +170,8 @@ export default function AgentsMcp() {
                                 {'\n'}
                                 {'}'}
                             
-                        
+
+

No token in the config. The bridge launches TablePro if it is not already running. diff --git a/resources/js/components/landing/download-rail.tsx b/resources/js/components/landing/download-rail.tsx index 471a93a..a60ee10 100644 --- a/resources/js/components/landing/download-rail.tsx +++ b/resources/js/components/landing/download-rail.tsx @@ -1,14 +1,8 @@ import Button from '@/components/ui/button'; import Container from '@/components/ui/container'; import { FullLine } from '@/components/ui/full-line'; +import { AppleGlyph } from '@/components/ui/glyph'; -function AppleGlyph() { - return ( - - ); -} interface Props { /** diff --git a/resources/js/components/landing/faq.tsx b/resources/js/components/landing/faq.tsx index ce2fb3c..14e408d 100644 --- a/resources/js/components/landing/faq.tsx +++ b/resources/js/components/landing/faq.tsx @@ -1,5 +1,6 @@ import Container from '@/components/ui/container'; import { FullLine } from '@/components/ui/full-line'; +import FaqList from '@/components/ui/faq-list'; import SectionShell from '@/components/ui/section-shell'; import { faqs as defaultFaqs, type FaqItem } from '@/data/faqs'; @@ -10,41 +11,19 @@ interface Props { headlineMuted?: string; } -function Column({ items, className }: { items: FaqItem[]; className?: string }) { - return ( -

- {items.map((faq, i) => ( -
-

{faq.question}

-

{faq.answer}

-
- ))} -
- ); -} export default function FAQ({ items = defaultFaqs, headline = 'Questions people actually ask.', headlineMuted = 'Short answers.', }: Props) { - const mid = Math.ceil(items.length / 2); return ( -
- - -
+
diff --git a/resources/js/components/landing/footer-cta.tsx b/resources/js/components/landing/footer-cta.tsx index 8de7a90..791e88e 100644 --- a/resources/js/components/landing/footer-cta.tsx +++ b/resources/js/components/landing/footer-cta.tsx @@ -7,6 +7,7 @@ import { FullLine } from '@/components/ui/full-line'; import { cellBorders, GridCell, type ColumnMap } from '@/components/ui/grid-cell'; import SectionShell from '@/components/ui/section-shell'; import Button from '@/components/ui/button'; +import { AppleGlyph } from '@/components/ui/glyph'; interface FlashMessage { type: 'success' | 'warning' | 'error'; @@ -34,13 +35,6 @@ function FlashStatus({ flash }: { flash?: FlashMessage | null }) { ); } -function AppleGlyph() { - return ( - - ); -} /** * A minimal stand-in for Inertia's useForm, used by the two anonymous email @@ -240,7 +234,7 @@ export default function FooterCTA() {
- + {BREW_COMMAND} )} @@ -250,7 +238,7 @@ function PricingCard({ tier, cycle, discountCode, discount, paymentProvider, tea
    {tier.features?.map((feature) => (
  • - + {feature}
  • ))} @@ -339,7 +327,6 @@ export default function Pricing({ paymentProvider, teamMinSeats }: { paymentProv > {/* What a license actually buys. Stated before the prices, on purpose. */} -
    @@ -359,17 +346,16 @@ export default function Pricing({ paymentProvider, teamMinSeats }: { paymentProv {/* Billing toggle */} -
    -
    +
    {cycles.map((c) => (
    diff --git a/resources/js/pages/Compare.tsx b/resources/js/pages/Compare.tsx index 174cdcd..7d514f5 100644 --- a/resources/js/pages/Compare.tsx +++ b/resources/js/pages/Compare.tsx @@ -4,9 +4,13 @@ import Footer from '@/components/landing/footer'; import Container from '@/components/ui/container'; import SEOHead from '@/components/seo/seo-head'; import { getComparisonBySlug } from '@/data/comparisons'; -import SectionLabel from '@/components/ui/section-label'; +import { PageHeader, SectionHeader } from '@/components/ui/section-shell'; import { FullLine } from '@/components/ui/full-line'; import Button from '@/components/ui/button'; +import { AppleGlyph, Availability, CheckGlyph } from '@/components/ui/glyph'; +import FaqList from '@/components/ui/faq-list'; +import ThemedImage from '@/components/ui/themed-image'; +import DataTable, { TABLE_COLUMN_RULE, TABLE_ROW_RULE } from '@/components/ui/data-table'; interface Props { slug: string; @@ -24,44 +28,10 @@ interface Props { * `muted-foreground/30` measured 1.51:1: both were effectively invisible to * anyone who needed them most. */ -function Check() { - return ( - <> - Included - - - ); -} -function Cross() { - return ( - <> - Not included - - - ); -} function CellValue({ value }: { value: string | boolean }) { - if (typeof value === 'boolean') return value ? : ; + if (typeof value === 'boolean') return ; return {value}; } @@ -134,73 +104,59 @@ export default function Compare({ slug, downloadUrls, githubStars }: Props) { { name: comp.name, path: canonical }, ]} /> - - {/* Hero */} -
    - - - - - Compare - - - - -
    - - - -

    - {comp.tagline} -

    - -
    - -
    - - - -

    - {comp.longDescription} -

    - -
    - - {/* Comparison Table */} + +{/* Comparison Table */}
    -
    -
    - {/* Header */} -
    -
    - Feature -
    -
    - TablePro -
    -
    - {comp.name} -
    -
    - - {/* Rows */} - {comp.rows.map((row) => ( -
    -
    - {row.label} -
    -
    - -
    -
    - -
    -
    - ))} -
    + {/* + * Same shape as the plan comparison on the homepage: a real + * table, column separators at the column weight, and the + * scroll container reachable by keyboard. This was a grid of + * divs with no table semantics, drawing its columns at the + * row weight — in the one table where the columns carry the + * entire meaning. + */} +
    + + + + + Feature + + + TablePro + + + {comp.name} + + + + + {comp.rows.map((row) => ( + + + {row.label} + + + + + + + + + ))} + +
    @@ -208,28 +164,10 @@ export default function Compare({ slug, downloadUrls, githubStars }: Props) { {/* Benchmarks */} {comp.benchmarks && ( <> -
    - - - - - Benchmarks - - - - -
    - - - -

    - The numbers. -

    - -
    - -
    - +
    @@ -260,28 +198,10 @@ export default function Compare({ slug, downloadUrls, githubStars }: Props) { )} {/* Pros */} -
    - - - - - Summary - - - - -
    - - - -

    - Strengths of each. -

    - -
    - -
    - +
    @@ -291,7 +211,7 @@ export default function Compare({ slug, downloadUrls, githubStars }: Props) {
      {comp.prosTablePro.map((pro) => (
    • - + {pro}
    • ))} @@ -304,7 +224,7 @@ export default function Compare({ slug, downloadUrls, githubStars }: Props) {
        {comp.prosCompetitor.map((pro) => (
      • - + {pro}
      • ))} @@ -317,28 +237,10 @@ export default function Compare({ slug, downloadUrls, githubStars }: Props) { {/* Migration guide */} {comp.migrationSteps && comp.migrationSteps.length > 0 && ( <> -
        - - - - - Migration - - - - -
        - - - -

        - Switch from {comp.name}. -

        - -
        - -
        - + Switch from {comp.name}.} + />
          @@ -360,84 +262,29 @@ export default function Compare({ slug, downloadUrls, githubStars }: Props) { )} {/* App Screenshot */} -
          - - - - - TablePro - - - - -
          - - - -

          - See it in action. -

          - -
          - -
          - + - - - TablePro interface showing the data grid and SQL editor - - - - TablePro interface showing the data grid and SQL editor - + {/* Who Should Choose What */} -
          - - - - - Decision - - - - -
          - - - -

          - Which one is right for you? -

          - -
          - -
          - +
          @@ -452,21 +299,8 @@ export default function Compare({ slug, downloadUrls, githubStars }: Props) {
          - - {/* Verdict */} -
          - - - - - Verdict - - - - -
          - - + +

          @@ -479,43 +313,13 @@ export default function Compare({ slug, downloadUrls, githubStars }: Props) { {/* FAQ */} {comp.faqs && comp.faqs.length > 0 && ( <> -

          - - - - - FAQ - - - - -
          - - - -

          - Common questions. -

          - -
          - -
          - + -
          - {comp.faqs.map((faq) => ( -
          - - {faq.question} - - - - -

          {faq.answer}

          -
          - ))} -
          +
          @@ -537,7 +341,7 @@ export default function Compare({ slug, downloadUrls, githubStars }: Props) {
          diff --git a/resources/js/pages/DatabaseClient.tsx b/resources/js/pages/DatabaseClient.tsx index d10c396..950433b 100644 --- a/resources/js/pages/DatabaseClient.tsx +++ b/resources/js/pages/DatabaseClient.tsx @@ -4,9 +4,12 @@ import Footer from '@/components/landing/footer'; import Container from '@/components/ui/container'; import SEOHead from '@/components/seo/seo-head'; import { getDatabaseBySlug } from '@/data/databases'; -import SectionLabel from '@/components/ui/section-label'; +import { PageHeader, SectionHeader } from '@/components/ui/section-shell'; import { FullLine } from '@/components/ui/full-line'; import Button from '@/components/ui/button'; +import { AppleGlyph, CheckGlyph } from '@/components/ui/glyph'; +import FaqList from '@/components/ui/faq-list'; +import ThemedImage from '@/components/ui/themed-image'; interface Props { slug: string; @@ -96,40 +99,18 @@ export default function DatabaseClient({ slug, downloadUrls, githubStars }: Prop /> {/* Hero */} -
          - - - -
          - {db.name} - + + {db.name} {db.name} Client - -
          - -
          - -
          - - - -

          - {db.tagline} -

          - -
          + + } + headline={db.tagline} + lede={db.longDescription} + /> -
          - - - -

          - {db.longDescription} -

          - -
          - -
          +
          @@ -137,7 +118,7 @@ export default function DatabaseClient({ slug, downloadUrls, githubStars }: Prop