dioxus_docs_kit/components/
docs_page.rs1use dioxus::prelude::*;
2use dioxus_mdx::{DocContent, DocTableOfContents, EndpointPage, extract_headers};
3
4use crate::DocsContext;
5use crate::registry::DocsRegistry;
6
7use super::copy_page::CopyPageButton;
8use super::docs_layout::LayoutOffsets;
9use super::docs_meta::DocsPageMeta;
10use super::page_nav::DocsPageNav;
11
12#[component]
27pub fn DocsPageContent(path: String, article_footer: Option<Element>) -> Element {
28 let registry = use_context::<&'static DocsRegistry>();
29 let ctx = use_context::<DocsContext>();
30
31 if let Some((operation, spec)) = registry.get_api_operation_with_spec(&path) {
33 return rsx! {
34 DocsPageMeta { path: path.clone() }
35 div { class: "dk-endpoint flex flex-col",
36 EndpointPage { operation: operation.clone(), spec: spec.clone() }
37 main { class: "px-8 lg:px-12 pb-12",
38 div { class: "max-w-2xl",
39 if let Some(ft) = article_footer {
40 div { class: "dk-article-footer-slot mb-6", {ft} }
41 }
42 DocsPageNav { current_path: path.clone() }
43 }
44 }
45 }
46 };
47 }
48
49 let offsets = try_use_context::<LayoutOffsets>().unwrap_or(LayoutOffsets {
50 sticky_top: "top-20",
51 scroll_mt: "scroll-mt-20",
52 sidebar_height: "h-[calc(100vh-5rem)]",
53 });
54
55 let doc = match registry.get_parsed_doc(&path) {
56 Some(d) => d,
57 None => {
58 let base = ctx.base_path.clone();
59 return rsx! {
60 div { class: "container mx-auto px-8 py-12 max-w-4xl",
61 div { class: "text-center",
62 h1 { class: "text-4xl font-bold mb-4", "404" }
63 p { class: "text-base-content/70 mb-8",
64 "Page not found: {path}"
65 }
66 Link {
67 to: NavigationTarget::Internal(base),
68 class: "btn btn-primary",
69 "Go to Documentation"
70 }
71 }
72 }
73 };
74 }
75 };
76
77 let headers = extract_headers(&doc.raw_markdown);
78
79 rsx! {
80 DocsPageMeta { path: path.clone() }
81 div { class: "flex",
82 main { class: "flex-1 min-w-0 px-8 py-12 lg:px-12",
84 article { class: "dk-article max-w-3xl mx-auto",
85 header { class: "dk-article-header mb-8 pb-8 border-b border-base-300",
87 div { class: "flex items-start justify-between gap-4",
88 h1 { class: "dk-article-title text-4xl font-bold tracking-tight mb-3",
89 "{doc.frontmatter.title}"
90 }
91 if !doc.raw_markdown.is_empty() {
92 CopyPageButton { content: doc.raw_markdown.clone() }
93 }
94 }
95 if let Some(desc) = &doc.frontmatter.description {
96 p { class: "dk-article-description text-lg text-base-content/70",
97 "{desc}"
98 }
99 }
100 }
101
102 div { class: "dk-article-body prose prose-base max-w-none
104 prose-headings:{offsets.scroll_mt}
105 prose-h2:text-2xl prose-h2:font-semibold prose-h2:mt-10 prose-h2:mb-4
106 prose-h3:text-xl prose-h3:font-medium prose-h3:mt-8 prose-h3:mb-3
107 prose-p:text-base-content/80 prose-p:leading-relaxed
108 prose-a:text-primary prose-a:no-underline hover:prose-a:underline
109 prose-code:bg-base-200 prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded prose-code:text-sm",
110 DocContent { nodes: doc.content.clone() }
111 }
112
113 if let Some(ft) = article_footer {
115 div { class: "dk-article-footer-slot mt-12", {ft} }
116 }
117
118 DocsPageNav { current_path: path.clone() }
120 }
121 }
122
123 if !headers.is_empty() {
125 aside { class: "dk-toc w-56 shrink-0 hidden xl:block",
126 div { class: "sticky {offsets.sticky_top} p-6",
127 DocTableOfContents { headers }
128 }
129 }
130 }
131 }
132 }
133}