dioxus_mdx/components/openapi/
responses_list.rs1use dioxus::prelude::*;
4use dioxus_free_icons::{Icon, icons::ld_icons::*};
5
6use crate::parser::ApiResponse;
7
8use super::schema_viewer::SchemaViewer;
9
10#[derive(Props, Clone, PartialEq)]
12pub struct ResponsesListProps {
13 pub responses: Vec<ApiResponse>,
15}
16
17#[component]
19pub fn ResponsesList(props: ResponsesListProps) -> Element {
20 if props.responses.is_empty() {
21 return rsx! {};
22 }
23
24 rsx! {
25 div { class: "space-y-2",
26 for response in &props.responses {
27 ResponseItem { key: "{response.status_code}", response: response.clone() }
28 }
29 }
30 }
31}
32
33#[derive(Props, Clone, PartialEq)]
35pub struct ResponseItemProps {
36 pub response: ApiResponse,
38}
39
40#[component]
42pub fn ResponseItem(props: ResponseItemProps) -> Element {
43 let mut is_expanded = use_signal(|| false);
44 let response = &props.response;
45 let badge_class = response.status_badge_class();
46
47 let has_content = !response.content.is_empty();
48
49 rsx! {
50 div { class: "border border-base-300 rounded-lg overflow-hidden",
51 button {
53 class: "w-full flex items-center gap-3 px-3 py-2 text-left hover:bg-base-200 transition-colors",
54 disabled: !has_content,
55 onclick: move |_| {
56 if has_content {
57 is_expanded.set(!is_expanded());
58 }
59 },
60
61 if has_content {
63 Icon {
64 class: if is_expanded() { "size-4 text-base-content/50 transform rotate-90 transition-transform" } else { "size-4 text-base-content/50 transition-transform" },
65 icon: LdChevronRight
66 }
67 }
68
69 span { class: "badge {badge_class} badge-sm font-mono font-bold",
71 "{response.status_code}"
72 }
73
74 span { class: "text-sm text-base-content/70 flex-1",
76 "{response.description}"
77 }
78 }
79
80 if is_expanded() && has_content {
82 div { class: "border-t border-base-300 bg-base-200/30",
83 for content in &response.content {
84 div { class: "p-3",
85 div { class: "mb-2",
87 code { class: "text-xs font-mono text-base-content/50",
88 "{content.media_type}"
89 }
90 }
91
92 if let Some(schema) = &content.schema {
94 SchemaViewer {
95 schema: schema.clone(),
96 expanded: true,
97 }
98 }
99
100 if let Some(example) = &content.example {
102 div { class: "mt-3 p-2 bg-base-300 rounded",
103 span { class: "text-xs text-base-content/50 font-semibold", "Example" }
104 pre { class: "mt-1 text-xs font-mono text-secondary overflow-x-auto whitespace-pre-wrap",
105 "{example}"
106 }
107 }
108 }
109 }
110 }
111 }
112 }
113 }
114 }
115}