Skip to content

Commit 41491a7

Browse files
authored
ENG-6174: Card component (#15)
1 parent 2f26609 commit 41491a7

File tree

2 files changed

+142
-0
lines changed

2 files changed

+142
-0
lines changed

reflex_ui/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"components.base.avatar": ["avatar"],
77
"components.base.badge": ["badge"],
88
"components.base.button": ["button"],
9+
"components.base.card": ["card"],
910
"components.base.checkbox": ["checkbox"],
1011
"components.base.scroll_area": ["scroll_area"],
1112
"components.base.select": ["select"],

reflex_ui/components/base/card.py

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
"""Custom card component."""
2+
3+
from reflex.components.component import Component, ComponentNamespace
4+
from reflex.components.el import Div
5+
from reflex.vars import Var
6+
7+
from reflex_ui.components.component import CoreComponent
8+
9+
10+
class ClassNames:
11+
"""Class names for the card component."""
12+
13+
ROOT = "rounded-xl border border-secondary-a4 bg-secondary-1 shadow-small"
14+
HEADER = "flex flex-col gap-2 p-6"
15+
TITLE = "text-2xl font-semibold text-secondary-12"
16+
DESCRIPTION = "text-sm text-secondary-11 font-[450]"
17+
CONTENT = "flex flex-col gap-4 px-6 pb-6"
18+
FOOTER = "flex flex-row justify-between items-center px-6 pb-6"
19+
20+
21+
class CardComponent(Div, CoreComponent):
22+
"""Base component for the card component."""
23+
24+
25+
class CardRoot(CardComponent):
26+
"""A card component that displays content in a card format."""
27+
28+
@classmethod
29+
def create(cls, *children, **props):
30+
"""Create the card component."""
31+
props["data-slot"] = "card"
32+
cls.set_class_name(ClassNames.ROOT, props)
33+
return super().create(*children, **props)
34+
35+
36+
class CardHeader(CardComponent):
37+
"""A header component for the card."""
38+
39+
@classmethod
40+
def create(cls, *children, **props):
41+
"""Create the card header component."""
42+
props["data-slot"] = "card-header"
43+
cls.set_class_name(ClassNames.HEADER, props)
44+
return super().create(*children, **props)
45+
46+
47+
class CardTitle(CardComponent):
48+
"""A title component for the card."""
49+
50+
@classmethod
51+
def create(cls, *children, **props):
52+
"""Create the card title component."""
53+
props["data-slot"] = "card-title"
54+
cls.set_class_name(ClassNames.TITLE, props)
55+
return super().create(*children, **props)
56+
57+
58+
class CardDescription(CardComponent):
59+
"""A description component for the card."""
60+
61+
@classmethod
62+
def create(cls, *children, **props):
63+
"""Create the card description component."""
64+
props["data-slot"] = "card-description"
65+
cls.set_class_name(ClassNames.DESCRIPTION, props)
66+
return super().create(*children, **props)
67+
68+
69+
class CardContent(CardComponent):
70+
"""A content component for the card."""
71+
72+
@classmethod
73+
def create(cls, *children, **props):
74+
"""Create the card content component."""
75+
props["data-slot"] = "card-content"
76+
cls.set_class_name(ClassNames.CONTENT, props)
77+
return super().create(*children, **props)
78+
79+
80+
class CardFooter(CardComponent):
81+
"""A footer component for the card."""
82+
83+
@classmethod
84+
def create(cls, *children, **props):
85+
"""Create the card footer component."""
86+
props["data-slot"] = "card-footer"
87+
cls.set_class_name(ClassNames.FOOTER, props)
88+
return super().create(*children, **props)
89+
90+
91+
class HighLevelCard(CardComponent):
92+
"""A high level card component that displays content in a card format."""
93+
94+
# Card props
95+
title: Var[str | Component | None]
96+
description: Var[str | Component | None]
97+
content: Var[str | Component | None]
98+
footer: Var[str | Component | None]
99+
100+
@classmethod
101+
def create(cls, *children, **props):
102+
"""Create the card component."""
103+
title = props.pop("title", "")
104+
description = props.pop("description", "")
105+
content = props.pop("content", "")
106+
footer = props.pop("footer", "")
107+
108+
return CardRoot.create(
109+
CardHeader.create(
110+
CardTitle.create(title) if title else None,
111+
CardDescription.create(description) if description else None,
112+
),
113+
CardContent.create(content) if content else None,
114+
CardFooter.create(footer) if footer else None,
115+
*children,
116+
**props,
117+
)
118+
119+
def _exclude_props(self) -> list[str]:
120+
return [
121+
*super()._exclude_props(),
122+
"title",
123+
"description",
124+
"content",
125+
"footer",
126+
]
127+
128+
129+
class Card(ComponentNamespace):
130+
"""A card component that displays content in a card format."""
131+
132+
root = staticmethod(CardRoot.create)
133+
header = staticmethod(CardHeader.create)
134+
title = staticmethod(CardTitle.create)
135+
description = staticmethod(CardDescription.create)
136+
content = staticmethod(CardContent.create)
137+
footer = staticmethod(CardFooter.create)
138+
__call__ = staticmethod(HighLevelCard.create)
139+
140+
141+
card = Card()

0 commit comments

Comments
 (0)