Culture log

A culture and sample record with supplied medium, conditions, chronological observations and host-owned recording actions.

Culture observations

Awaiting record review

Oldest dated observation first; undated records follow

  1. Sample record received

    Recorded
  2. Plate image attached

    Recorded
    Image and source annotations attached

Review a culture record

Sample 042 / Notebook

Culture 042 observations

Awaiting record review

Oldest dated observation first; undated records follow

  1. Sample record received

    Recorded
    Sample identity and medium batch copied from the source record
  2. Plate image attached

    Recorded
    Image P-042 and supplied colony annotations are available for review

Use it for

  • Review culture identity, sample identity, medium and conditions as supplied by the host.
  • Provide offset-bearing timestamps for chronological ordering. Equal timestamps retain their supplied order; missing and invalid timestamps sort after dated observations.
  • Supply actions and onAction to request recording changes. Update status or observations only when the host has accepted the change; pending disables actions without changing recorded state.
  • Use oldest or newest ordering for at most 256 observations, 32 conditions and 16 actions with unique non-empty identifiers.

Not for

  • Inferring organism identity, contamination, growth interpretation or culture success from a status or observation.
  • Generating a culture recipe, an incubation recommendation or a procedure from the displayed conditions.
  • Treating a requested recording action as confirmation that a laboratory procedure occurred.

Three ways in. They share one source, so the pixels match whichever you pick.

1. Import the package

npm install @noorddev/vlak-react

// once, next to your app's root
import "@noorddev/vlak-react/css";

import { CultureLog } from "@noorddev/vlak-react";

Precompiled React and one stylesheet. No compiler to configure. Per-component imports work too: @noorddev/vlak-react/components/culture-log.

2. Vendor the source

npx @noorddev/vlak-cli add culture-log

The StyleX leaf lands in components/vlak/ with its dependencies, for your own compiler to own. See StyleX.

3. Through shadcn

npx shadcn add https://vlak.dev/r/culture-log.json

The same registry item, installed by shadcn's CLI.

CSS only

<link rel="stylesheet" href="node_modules/@noorddev/vlak/css/vlak.css" />

No React. Link vlak.css and use the markup and classes below.

import { useState } from "react";
import { CultureLog } from "@noorddev/vlak-react";

function CultureRecord() {
  const [reviewed, setReviewed] = useState(false);
  return <CultureLog label="Culture observations" cultureId="C-042" sampleId="S-042" medium="Agar medium A" status={reviewed ? "Record review noted" : "Awaiting record review"} conditions={[{ id: "batch", label: "Medium batch", value: "M-17" }]} observations={[
    { id: "received", label: "Sample record received", dateTime: "2026-09-07T09:00:00+02:00", timeLabel: "7 September, 09:00", status: "Recorded" },
    { id: "image", label: "Plate image attached", dateTime: "2026-09-07T10:30:00+02:00", timeLabel: "7 September, 10:30", status: "Recorded", notes: "Image and source annotations attached" },
  ]} actions={reviewed ? [] : [{ id: "review", label: "Record review" }]} onAction={() => setReviewed(true)} />;
}

CultureLog

A chronological notebook of supplied culture observations, without protocol recommendations.

PropTypeDefaultDescription
labelrequiredstring
cultureIdrequiredstring
sampleIdrequiredstring
observationsrequiredreadonly CultureObservation[]
mediumReactNode
statusstring | null
conditionsreadonly CultureCondition[][]
actionsreadonly CultureAction[][]
onAction(actionId: string) => voidRequests a host recording action without changing any supplied observation or status.
pendingbooleanfalse
order"newest" | "oldest""oldest"

Also accepts HTMLAttributes<HTMLDivElement>.

KeysDoes
TabMoves between supplied links and enabled recording actions.
Enter, SpaceRequests the focused action through onAction without submitting a surrounding form.
<div class="rs-culture-log" role="group" aria-label="Culture observations"><div class="rs-culture-log-head"><p class="rs-culture-log-title">Culture observations</p><span class="rs-culture-log-copy">Awaiting record review</span></div><dl class="rs-culture-log-metadata"><div><dt class="rs-culture-log-copy">Culture</dt><dd class="rs-culture-log-value">C-042</dd></div><div><dt class="rs-culture-log-copy">Sample</dt><dd class="rs-culture-log-value">S-042</dd></div><div><dt class="rs-culture-log-copy">Medium</dt><dd class="rs-culture-log-value">Agar medium A</dd></div></dl><ol class="rs-culture-log-list"><li class="rs-culture-log-observation"><time class="rs-culture-log-time" datetime="2026-09-07T09:00:00+02:00">7 September, 09:00</time><div class="rs-culture-log-content"><p class="rs-culture-log-observation-label">Sample record received</p></div></li></ol></div>
.rs-culture-log.rs-culture-log-head.rs-culture-log-title.rs-culture-log-copy.rs-culture-log-metadata.rs-culture-log-value.rs-culture-log-list.rs-culture-log-observation.rs-culture-log-time.rs-culture-log-content.rs-culture-log-observation-label.rs-culture-log-notes.rs-culture-log-actions.rs-culture-log-action