chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
This commit is contained in:
+121
@@ -0,0 +1,121 @@
|
||||
import { cn } from '@sim/emcn'
|
||||
import {
|
||||
SolutionsCard,
|
||||
SolutionsCardRowHeader,
|
||||
} from '@/app/(landing)/components/solutions-page/components/solutions-card-row/components'
|
||||
import { SOLUTIONS_SPACING } from '@/app/(landing)/components/solutions-page/constants'
|
||||
import type { SolutionsCardRowConfig } from '@/app/(landing)/components/solutions-page/types'
|
||||
|
||||
/**
|
||||
* The enterprise feature sections rendered as ONE shared CSS grid so cards can
|
||||
* reflow across section boundaries in the two-column band (`sm`..`lg`,
|
||||
* 640-1023px). Separate per-section grids (what {@link SolutionsCardRow}
|
||||
* renders) leave an orphan cell there: each 3-card section breaks 2 + 1.
|
||||
*
|
||||
* Layout per breakpoint:
|
||||
* - `lg`+ (3 columns): source order - every header is followed by its own 3
|
||||
* cards, matching {@link SolutionsCardRow} exactly.
|
||||
* - `sm`..`lg` (2 columns): the `sm:max-lg:order-*` classes regroup the 12
|
||||
* cards into balanced blocks of 4 / 4 / 2 / 2 beneath the four headers, so
|
||||
* no grid cell is ever empty. Cards borrowed from the next section render
|
||||
* under the previous header in this band only.
|
||||
* - below `sm` (1 column): source order again - each header stacks above its
|
||||
* own 3 cards.
|
||||
*
|
||||
* Each section keeps its `<section aria-labelledby>` landmark via
|
||||
* `display: contents`, so its header and cards participate directly in the
|
||||
* outer grid while the document outline (H2 -> H3) and anchor ids stay
|
||||
* identical to the `SolutionsCardRow` markup.
|
||||
*
|
||||
* Vertical rhythm is reproduced from the flex-column layout it replaces: the
|
||||
* grid's own `gap-8` (32px) supplies the inter-card gap, and headers carry
|
||||
* margins that top the gap up to the original values - `mb-4` lands the
|
||||
* header->cards distance at 48px (`cardRowHeaderToGrid`), and the top margins
|
||||
* land the section->section distance at 120/88/64px (`sectionRhythm`).
|
||||
*/
|
||||
|
||||
interface EnterpriseFeatureGridProps {
|
||||
/** The four 3-card feature rows, in source order. */
|
||||
rows: SolutionsCardRowConfig[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Header top margins recreating `LANDING_SECTION_RHYTHM` (120/88/64px) on top
|
||||
* of the grid's 32px row gap; `mb-4` recreates `cardRowHeaderToGrid` (48px).
|
||||
*/
|
||||
const HEADER_RHYTHM = 'mt-[88px] mb-4 max-lg:mt-14 max-sm:mt-8'
|
||||
const FIRST_HEADER_RHYTHM = 'mb-4'
|
||||
|
||||
/** Two-column-band ordering for the four headers (positions 1, 6, 11, 14). */
|
||||
const TABLET_HEADER_ORDER = [
|
||||
'sm:max-lg:order-1',
|
||||
'sm:max-lg:order-6',
|
||||
'sm:max-lg:order-11',
|
||||
'sm:max-lg:order-[14]',
|
||||
] as const
|
||||
|
||||
/**
|
||||
* Two-column-band ordering for the 12 cards (flat index = rowIndex * 3 +
|
||||
* cardIndex), interleaved with {@link TABLET_HEADER_ORDER} to produce the
|
||||
* 4 / 4 / 2 / 2 grouping.
|
||||
*/
|
||||
const TABLET_CARD_ORDER = [
|
||||
'sm:max-lg:order-2',
|
||||
'sm:max-lg:order-3',
|
||||
'sm:max-lg:order-4',
|
||||
'sm:max-lg:order-5',
|
||||
'sm:max-lg:order-7',
|
||||
'sm:max-lg:order-8',
|
||||
'sm:max-lg:order-9',
|
||||
'sm:max-lg:order-10',
|
||||
'sm:max-lg:order-12',
|
||||
'sm:max-lg:order-[13]',
|
||||
'sm:max-lg:order-[15]',
|
||||
'sm:max-lg:order-[16]',
|
||||
] as const
|
||||
|
||||
export function EnterpriseFeatureGrid({ rows }: EnterpriseFeatureGridProps) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'grid grid-cols-3 max-sm:grid-cols-1 max-lg:grid-cols-2',
|
||||
SOLUTIONS_SPACING.cardGridGap
|
||||
)}
|
||||
>
|
||||
{rows.map((row, rowIndex) => {
|
||||
const headingId = `solutions-row-${row.id}-heading`
|
||||
|
||||
return (
|
||||
<section
|
||||
key={row.id}
|
||||
id={`solutions-row-${row.id}`}
|
||||
aria-labelledby={headingId}
|
||||
className='contents'
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
'col-span-full',
|
||||
rowIndex === 0 ? FIRST_HEADER_RHYTHM : HEADER_RHYTHM,
|
||||
TABLET_HEADER_ORDER[rowIndex]
|
||||
)}
|
||||
>
|
||||
<SolutionsCardRowHeader row={row} headingId={headingId} variant='feature' />
|
||||
</div>
|
||||
{row.cards.map((card, cardIndex) => (
|
||||
<div
|
||||
key={`${row.id}-${card.title}`}
|
||||
className={cn('min-w-0', TABLET_CARD_ORDER[rowIndex * 3 + cardIndex])}
|
||||
>
|
||||
<SolutionsCard
|
||||
card={card}
|
||||
headingId={`solutions-row-${row.id}-card-${cardIndex}-heading`}
|
||||
variant='featureTile'
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</section>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { EnterpriseFeatureGrid } from './enterprise-feature-grid'
|
||||
Reference in New Issue
Block a user