ContentDetail
ContentDetail is a scrollable compound component for content that may come from a FHIR Composition. The SDK supplies extraction helpers, but the app controls layout, loading, data fetching, and navigation.
import { ContentDetail } from "@ovok/native";
<ContentDetail composition={composition}>
<ContentDetail.Header>
<ContentDetail.Title />
<ContentDetail.Metadata>
<ContentDetail.Metadata.Author />
<ContentDetail.Metadata.Separator />
<ContentDetail.Metadata.Date />
</ContentDetail.Metadata>
</ContentDetail.Header>
<ContentDetail.Body>
<ContentDetail.RichContent />
</ContentDetail.Body>
<ContentDetail.Footer>
<ContentDetail.Tags />
<ContentDetail.Resource />
</ContentDetail.Footer>
</ContentDetail>;
Root and context
The root is a ScrollView, accepts ScrollViewProps plus optional composition, and provides that composition through context. Header, Body, and Footer render React Native View containers and accept ViewProps. Metadata also accepts ViewProps and lays out children in a row.
useComposition is a named export from @ovok/native and must be called below ContentDetail; outside the provider it throws useComposition must be used within a CompositionContext.
Title and rich content
ContentDetail.Titleaccepts optional string children or readscomposition.title. It throws if neither exists and renders PaperTextwithvariant="titleLarge".ContentDetail.RichContentacceptscontentplusRenderHTMLPropsexceptsource. Ifcontentis absent, it uses the first composition section withtext.div, without excluding sections codedreading-timeorresource-link; put the article body first or passcontentexplicitly. It throws when no HTML is available.- Rich content uses
react-native-render-html.<img>elements render throughOptimizedImage; caller-suppliedbaseStyle,customHTMLElementModels, andrenderersare merged with the SDK defaults.
Metadata
Metadata items render Paper Text with the bodyMedium variant by default.
Metadata.Authorusescomposition.meta.author.displayunless children are supplied.Metadata.Dateuses the top-levelcomposition.date, formats valid dates asdd MMM yyyy, and rendersInvalid datefor an invalid value.Metadata.ReadingTimefinds a section codedreading-time, strips HTML from itstext.div, and renders the result.Metadata.Itemis the base item for caller-owned content.Metadata.Separatordefaults to·.
Each item accepts optional children and Paper text props. There is no built-in author, date, reading-time, or error translation layer beyond the resource label below.
Tags and resource link
ContentDetail.Tags accepts optional tags?: Coding[], onTagPress, chipProps, and ViewProps. Without tags, it reads composition.meta.tag. Each tag displays tag.display or tag.code; the component returns null when there are no tags. chipProps cannot override the generated children or onPress.
ContentDetail.Resource looks for a composition section containing coding resource-link, extracts the URL using the current anchor parser, and opens it with expo-web-browser by default. Until the parser is corrected, make the anchor's visible text exactly the same as its href; otherwise the visible text can be returned as the URL. Supply onPress(resourceLink) to own the action. It returns null when no resource link is found. Its visible label is localized with content.detail.view-resource.
ContentDetail.Resource props
| Prop | Type | Default | Description |
|---|---|---|---|
onPress | (resourceLink: string) => void | Opens with expo-web-browser | Own the resource action. |
style | StyleProp<TextStyle> | undefined | Style for the resource label. |
testID | string | undefined | Test identifier. |
The matching Composition section must contain a coding with code: "resource-link"
and an HTML anchor in section.text.div, for example
<a href="https://example.com/manual">Manual</a>. A plain URL string is not parsed;
the current parser only works reliably when the visible anchor text is also the URL;
when no matching section or anchor is present, the component returns null.
The content-detail module uses only the content.detail.view-resource translation
key. Metadata values are formatted directly and do not use built-in content.metadata.*
or content.error.* keys.
Styling and ownership
The root adds theme-based gap and padding to contentContainerStyle; caller values are merged afterward. The component does not validate a FHIR resource beyond the fields it reads, does not load remote content, and does not own authentication, caching, or routing.