@aspect-ops/exon-ui 0.2.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -45
- package/dist/components/BottomNav/BottomNavItem.svelte +4 -3
- package/dist/components/BottomNav/BottomNavItem.svelte.d.ts +2 -1
- package/dist/components/CTASection/CTASection.svelte +298 -0
- package/dist/components/CTASection/CTASection.svelte.d.ts +15 -0
- package/dist/components/CTASection/index.d.ts +2 -0
- package/dist/components/CTASection/index.js +1 -0
- package/dist/components/DoughnutChart/DoughnutChart.svelte +4 -4
- package/dist/components/FlexibleGrid/FlexibleGrid.svelte +118 -0
- package/dist/components/FlexibleGrid/FlexibleGrid.svelte.d.ts +7 -0
- package/dist/components/FlexibleGrid/README.md +212 -0
- package/dist/components/FlexibleGrid/index.d.ts +2 -0
- package/dist/components/FlexibleGrid/index.js +1 -0
- package/dist/components/GlobalHeader/GlobalHeader.svelte +806 -0
- package/dist/components/GlobalHeader/GlobalHeader.svelte.d.ts +3 -0
- package/dist/components/GlobalHeader/index.d.ts +2 -0
- package/dist/components/GlobalHeader/index.js +1 -0
- package/dist/components/Hero/Hero.svelte +306 -0
- package/dist/components/Hero/Hero.svelte.d.ts +18 -0
- package/dist/components/Hero/index.d.ts +2 -0
- package/dist/components/Hero/index.js +1 -0
- package/dist/components/HeroLeftAligned/HeroLeftAligned.svelte +182 -0
- package/dist/components/HeroLeftAligned/HeroLeftAligned.svelte.d.ts +8 -0
- package/dist/components/HeroLeftAligned/README.md +168 -0
- package/dist/components/HeroLeftAligned/index.d.ts +2 -0
- package/dist/components/HeroLeftAligned/index.js +1 -0
- package/dist/components/IconFeatureCard/IconFeatureCard.svelte +173 -0
- package/dist/components/IconFeatureCard/IconFeatureCard.svelte.d.ts +4 -0
- package/dist/components/IconFeatureCard/README.md +234 -0
- package/dist/components/IconFeatureCard/index.d.ts +2 -0
- package/dist/components/IconFeatureCard/index.js +1 -0
- package/dist/components/ImageTextCard/ImageTextCard.svelte +149 -0
- package/dist/components/ImageTextCard/ImageTextCard.svelte.d.ts +22 -0
- package/dist/components/ImageTextCard/README.md +177 -0
- package/dist/components/ImageTextCard/index.d.ts +2 -0
- package/dist/components/ImageTextCard/index.js +1 -0
- package/dist/components/LogoCloud/LogoCloud.svelte +333 -0
- package/dist/components/LogoCloud/LogoCloud.svelte.d.ts +20 -0
- package/dist/components/LogoCloud/index.d.ts +2 -0
- package/dist/components/LogoCloud/index.js +1 -0
- package/dist/components/ServiceCard/ServiceCard.svelte +359 -0
- package/dist/components/ServiceCard/ServiceCard.svelte.d.ts +16 -0
- package/dist/components/ServiceCard/index.d.ts +1 -0
- package/dist/components/ServiceCard/index.js +1 -0
- package/dist/components/Sidebar/SidebarGroup.svelte +1 -4
- package/dist/components/SplitSection/SplitSection.svelte +194 -0
- package/dist/components/SplitSection/SplitSection.svelte.d.ts +15 -0
- package/dist/components/SplitSection/index.d.ts +1 -0
- package/dist/components/SplitSection/index.js +1 -0
- package/dist/components/TestimonialCard/TestimonialCard.svelte +290 -0
- package/dist/components/TestimonialCard/TestimonialCard.svelte.d.ts +14 -0
- package/dist/components/TestimonialCard/index.d.ts +1 -0
- package/dist/components/TestimonialCard/index.js +1 -0
- package/dist/components/Timeline/Timeline.svelte +444 -0
- package/dist/components/Timeline/Timeline.svelte.d.ts +19 -0
- package/dist/components/Timeline/index.d.ts +2 -0
- package/dist/components/Timeline/index.js +1 -0
- package/dist/index.d.ts +23 -1
- package/dist/index.js +13 -1
- package/dist/types/index.d.ts +49 -1
- package/dist/types/layout.d.ts +20 -0
- package/package.json +9 -2
- package/dist/components/Mermaid/Mermaid.svelte +0 -320
- package/dist/components/Mermaid/Mermaid.svelte.d.ts +0 -38
- package/dist/components/Mermaid/index.d.ts +0 -1
- package/dist/components/Mermaid/index.js +0 -1
- package/dist/components/Mermaid/mermaid.d.ts +0 -21
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { IconFeatureCardProps } from '../../types/index.js';
|
|
3
|
+
|
|
4
|
+
let {
|
|
5
|
+
icon,
|
|
6
|
+
iconAlt = '',
|
|
7
|
+
title,
|
|
8
|
+
features,
|
|
9
|
+
topBgColor = '#B85C5C',
|
|
10
|
+
iconBgColor = 'white',
|
|
11
|
+
iconSize = '4rem',
|
|
12
|
+
iconContainerSize = '6rem',
|
|
13
|
+
titleColor = '#1F2937',
|
|
14
|
+
titleFontSize = '1.75rem',
|
|
15
|
+
featureColor = '#4B5563',
|
|
16
|
+
featureFontSize = '1.125rem',
|
|
17
|
+
borderRadius = '1rem',
|
|
18
|
+
padding = '2rem',
|
|
19
|
+
featureGap = '0.875rem',
|
|
20
|
+
bulletColor = '#9CA3AF',
|
|
21
|
+
class: className = ''
|
|
22
|
+
}: IconFeatureCardProps = $props();
|
|
23
|
+
|
|
24
|
+
// Validate required props
|
|
25
|
+
const hasIcon = $derived(!!icon);
|
|
26
|
+
const hasTitle = $derived(!!title);
|
|
27
|
+
const hasFeatures = $derived(features && features.length > 0);
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<div
|
|
31
|
+
class="icon-feature-card {className}"
|
|
32
|
+
style:--top-bg-color={topBgColor}
|
|
33
|
+
style:--icon-bg-color={iconBgColor}
|
|
34
|
+
style:--icon-size={iconSize}
|
|
35
|
+
style:--icon-container-size={iconContainerSize}
|
|
36
|
+
style:--title-color={titleColor}
|
|
37
|
+
style:--title-font-size={titleFontSize}
|
|
38
|
+
style:--feature-color={featureColor}
|
|
39
|
+
style:--feature-font-size={featureFontSize}
|
|
40
|
+
style:--border-radius={borderRadius}
|
|
41
|
+
style:--padding={padding}
|
|
42
|
+
style:--feature-gap={featureGap}
|
|
43
|
+
style:--bullet-color={bulletColor}
|
|
44
|
+
>
|
|
45
|
+
<!-- Top Section: Icon/Badge -->
|
|
46
|
+
<div class="icon-section">
|
|
47
|
+
{#if hasIcon}
|
|
48
|
+
<div class="icon-container">
|
|
49
|
+
<img src={icon} alt={iconAlt} class="icon-image" />
|
|
50
|
+
</div>
|
|
51
|
+
{/if}
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<!-- Bottom Section: Title and Features -->
|
|
55
|
+
<div class="content-section">
|
|
56
|
+
{#if hasTitle}
|
|
57
|
+
<h3 class="card-title">{title}</h3>
|
|
58
|
+
{/if}
|
|
59
|
+
{#if hasFeatures}
|
|
60
|
+
<ul class="features-list">
|
|
61
|
+
{#each features as feature}
|
|
62
|
+
<li class="feature-item">{feature}</li>
|
|
63
|
+
{/each}
|
|
64
|
+
</ul>
|
|
65
|
+
{/if}
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<style>
|
|
70
|
+
.icon-feature-card {
|
|
71
|
+
display: flex;
|
|
72
|
+
flex-direction: column;
|
|
73
|
+
border-radius: var(--border-radius);
|
|
74
|
+
overflow: hidden;
|
|
75
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
76
|
+
transition: all 0.3s ease;
|
|
77
|
+
font-family: inherit;
|
|
78
|
+
background: white;
|
|
79
|
+
height: 450px;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.icon-feature-card:hover {
|
|
83
|
+
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.15);
|
|
84
|
+
transform: translateY(-2px);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* Top Section: Icon/Badge - 35% of card */
|
|
88
|
+
.icon-section {
|
|
89
|
+
background-color: var(--top-bg-color);
|
|
90
|
+
display: flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
justify-content: center;
|
|
93
|
+
padding: var(--padding);
|
|
94
|
+
height: 35%;
|
|
95
|
+
box-sizing: border-box;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.icon-container {
|
|
99
|
+
width: var(--icon-container-size);
|
|
100
|
+
height: var(--icon-container-size);
|
|
101
|
+
background-color: var(--icon-bg-color);
|
|
102
|
+
border-radius: 50%;
|
|
103
|
+
display: flex;
|
|
104
|
+
align-items: center;
|
|
105
|
+
justify-content: center;
|
|
106
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.icon-image {
|
|
110
|
+
width: var(--icon-size);
|
|
111
|
+
height: var(--icon-size);
|
|
112
|
+
object-fit: contain;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/* Bottom Section: Content - 65% of card */
|
|
116
|
+
.content-section {
|
|
117
|
+
background-color: white;
|
|
118
|
+
padding: var(--padding);
|
|
119
|
+
height: 65%;
|
|
120
|
+
box-sizing: border-box;
|
|
121
|
+
display: flex;
|
|
122
|
+
flex-direction: column;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.card-title {
|
|
126
|
+
color: var(--title-color);
|
|
127
|
+
font-size: var(--title-font-size);
|
|
128
|
+
font-weight: 600;
|
|
129
|
+
margin: 0 0 1.5rem 0;
|
|
130
|
+
line-height: 1.3;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.features-list {
|
|
134
|
+
list-style: none;
|
|
135
|
+
padding: 0;
|
|
136
|
+
margin: 0;
|
|
137
|
+
display: flex;
|
|
138
|
+
flex-direction: column;
|
|
139
|
+
gap: var(--feature-gap);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.feature-item {
|
|
143
|
+
color: var(--feature-color);
|
|
144
|
+
font-size: var(--feature-font-size);
|
|
145
|
+
line-height: 1.6;
|
|
146
|
+
padding-left: 1.5rem;
|
|
147
|
+
position: relative;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.feature-item::before {
|
|
151
|
+
content: '•';
|
|
152
|
+
position: absolute;
|
|
153
|
+
left: 0;
|
|
154
|
+
color: var(--bullet-color);
|
|
155
|
+
font-size: 1.25rem;
|
|
156
|
+
line-height: 1.6;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* Responsive Design */
|
|
160
|
+
@media (max-width: 768px) {
|
|
161
|
+
.icon-feature-card {
|
|
162
|
+
height: 400px;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.card-title {
|
|
166
|
+
font-size: 1.5rem;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.feature-item {
|
|
170
|
+
font-size: 1rem;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
</style>
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# IconFeatureCard
|
|
2
|
+
|
|
3
|
+
A vertical card component featuring an icon section at the top and a feature list below. Perfect for showcasing services, features, or offerings with key highlights displayed as bullet points.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Vertical two-section layout (colored icon section + white content section)
|
|
8
|
+
- Top section with centered circular icon/badge on customizable colored background
|
|
9
|
+
- Bottom section with title and bulleted feature list
|
|
10
|
+
- Fully customizable colors and sizing
|
|
11
|
+
- Responsive design with mobile adjustments
|
|
12
|
+
- Hover effects with smooth transitions
|
|
13
|
+
- Accessibility support
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
### Basic Example
|
|
18
|
+
|
|
19
|
+
```svelte
|
|
20
|
+
<script>
|
|
21
|
+
import { IconFeatureCard } from '@aspect-ops/exon-ui';
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<IconFeatureCard
|
|
25
|
+
icon="/icons/support-24-7.svg"
|
|
26
|
+
iconAlt="24/7 Support icon"
|
|
27
|
+
title="Technical Support"
|
|
28
|
+
features={[
|
|
29
|
+
'Round-the-clock availability',
|
|
30
|
+
'Expert technical assistance',
|
|
31
|
+
'Fast response times',
|
|
32
|
+
'Multi-channel support'
|
|
33
|
+
]}
|
|
34
|
+
topBgColor="#3B82F6"
|
|
35
|
+
/>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### With Custom Colors
|
|
39
|
+
|
|
40
|
+
```svelte
|
|
41
|
+
<IconFeatureCard
|
|
42
|
+
icon="/icons/cloud-service.svg"
|
|
43
|
+
iconAlt="Cloud service icon"
|
|
44
|
+
title="Cloud Solutions"
|
|
45
|
+
features={['Scalable infrastructure', 'High availability', 'Automated backups', 'Global CDN']}
|
|
46
|
+
topBgColor="#10B981"
|
|
47
|
+
iconBgColor="#D1FAE5"
|
|
48
|
+
titleColor="#065F46"
|
|
49
|
+
featureColor="#047857"
|
|
50
|
+
/>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Custom Sizing
|
|
54
|
+
|
|
55
|
+
```svelte
|
|
56
|
+
<IconFeatureCard
|
|
57
|
+
icon="/icons/consulting.svg"
|
|
58
|
+
iconAlt="Consulting icon"
|
|
59
|
+
title="Expert Consulting"
|
|
60
|
+
features={['Strategic planning', 'Industry expertise', 'Best practices', 'Actionable insights']}
|
|
61
|
+
topBgColor="#8B5CF6"
|
|
62
|
+
iconSize="5rem"
|
|
63
|
+
iconContainerSize="7rem"
|
|
64
|
+
titleFontSize="2rem"
|
|
65
|
+
padding="2.5rem"
|
|
66
|
+
/>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Props
|
|
70
|
+
|
|
71
|
+
| Prop | Type | Default | Description |
|
|
72
|
+
| ------------------- | ---------- | ------------ | -------------------------------------------- |
|
|
73
|
+
| `icon` | `string` | **required** | Icon/image URL or path |
|
|
74
|
+
| `iconAlt` | `string` | `''` | Alt text for accessibility |
|
|
75
|
+
| `title` | `string` | **required** | Card title |
|
|
76
|
+
| `features` | `string[]` | **required** | Array of feature items to display as bullets |
|
|
77
|
+
| `topBgColor` | `string` | `'#B85C5C'` | Background color for top icon section |
|
|
78
|
+
| `iconBgColor` | `string` | `'white'` | Background color for circular icon container |
|
|
79
|
+
| `iconSize` | `string` | `'4rem'` | Size of the icon/image |
|
|
80
|
+
| `iconContainerSize` | `string` | `'6rem'` | Size of the circular icon container |
|
|
81
|
+
| `titleColor` | `string` | `'#1F2937'` | Title text color |
|
|
82
|
+
| `titleFontSize` | `string` | `'1.75rem'` | Title font size |
|
|
83
|
+
| `featureColor` | `string` | `'#4B5563'` | Feature list text color |
|
|
84
|
+
| `featureFontSize` | `string` | `'1.125rem'` | Feature list font size |
|
|
85
|
+
| `borderRadius` | `string` | `'1rem'` | Card border radius |
|
|
86
|
+
| `padding` | `string` | `'2rem'` | Padding for both sections |
|
|
87
|
+
| `featureGap` | `string` | `'0.875rem'` | Gap between feature list items |
|
|
88
|
+
| `bulletColor` | `string` | `'#9CA3AF'` | Color of the bullet points |
|
|
89
|
+
| `class` | `string` | `''` | Additional CSS classes |
|
|
90
|
+
|
|
91
|
+
## Styling
|
|
92
|
+
|
|
93
|
+
The component uses CSS custom properties for theming and inherits font-family from the parent.
|
|
94
|
+
|
|
95
|
+
### Hover Effect
|
|
96
|
+
|
|
97
|
+
The card has a built-in hover effect that lifts the card slightly and enhances the shadow:
|
|
98
|
+
|
|
99
|
+
- Transform: `translateY(-2px)`
|
|
100
|
+
- Shadow increases from `0 4px 6px` to `0 8px 12px`
|
|
101
|
+
|
|
102
|
+
### Layout Proportions
|
|
103
|
+
|
|
104
|
+
The card maintains a fixed proportion with `box-sizing: border-box` to include padding in calculations:
|
|
105
|
+
|
|
106
|
+
- **Icon Section (Top)**: Exactly 35% of card height (including padding)
|
|
107
|
+
- **Content Section (Bottom)**: Exactly 65% of card height (including padding)
|
|
108
|
+
- **Card Height**: Fixed at 450px (400px on mobile)
|
|
109
|
+
|
|
110
|
+
### Icon Section
|
|
111
|
+
|
|
112
|
+
The icon section features:
|
|
113
|
+
|
|
114
|
+
- Customizable colored background
|
|
115
|
+
- Centered circular icon container with white background (customizable)
|
|
116
|
+
- Drop shadow on icon container for depth
|
|
117
|
+
- Takes up 35% of card height
|
|
118
|
+
|
|
119
|
+
### Content Section
|
|
120
|
+
|
|
121
|
+
The content section features:
|
|
122
|
+
|
|
123
|
+
- White background
|
|
124
|
+
- Title with configurable color and size
|
|
125
|
+
- Bulleted list with custom bullet color
|
|
126
|
+
- Flexible gap spacing between items
|
|
127
|
+
- Takes up 65% of card height
|
|
128
|
+
|
|
129
|
+
## Accessibility
|
|
130
|
+
|
|
131
|
+
- Image `alt` text supported via `iconAlt` prop
|
|
132
|
+
- Semantic HTML with `<h3>` for title and `<ul>/<li>` for features
|
|
133
|
+
- Sufficient color contrast for text
|
|
134
|
+
- Inherits font-family for consistent typography
|
|
135
|
+
- Keyboard navigation friendly
|
|
136
|
+
|
|
137
|
+
## Responsive Design
|
|
138
|
+
|
|
139
|
+
- **Desktop:** Full layout with standard sizing
|
|
140
|
+
- **Mobile (≤768px):**
|
|
141
|
+
- Reduced icon section height (12rem → 10rem)
|
|
142
|
+
- Smaller title font (1.75rem → 1.5rem)
|
|
143
|
+
- Smaller feature font (1.125rem → 1rem)
|
|
144
|
+
|
|
145
|
+
## Examples
|
|
146
|
+
|
|
147
|
+
### Service Showcase
|
|
148
|
+
|
|
149
|
+
```svelte
|
|
150
|
+
<div class="services-grid">
|
|
151
|
+
<IconFeatureCard
|
|
152
|
+
icon="/icons/support.svg"
|
|
153
|
+
iconAlt="Support"
|
|
154
|
+
title="24/7 Support"
|
|
155
|
+
features={[
|
|
156
|
+
'Round-the-clock assistance',
|
|
157
|
+
'Expert support team',
|
|
158
|
+
'Fast response times',
|
|
159
|
+
'Multi-channel support'
|
|
160
|
+
]}
|
|
161
|
+
topBgColor="#3B82F6"
|
|
162
|
+
/>
|
|
163
|
+
<IconFeatureCard
|
|
164
|
+
icon="/icons/security.svg"
|
|
165
|
+
iconAlt="Security"
|
|
166
|
+
title="Enterprise Security"
|
|
167
|
+
features={[
|
|
168
|
+
'End-to-end encryption',
|
|
169
|
+
'SOC 2 compliance',
|
|
170
|
+
'Regular security audits',
|
|
171
|
+
'Data protection'
|
|
172
|
+
]}
|
|
173
|
+
topBgColor="#10B981"
|
|
174
|
+
/>
|
|
175
|
+
<IconFeatureCard
|
|
176
|
+
icon="/icons/performance.svg"
|
|
177
|
+
iconAlt="Performance"
|
|
178
|
+
title="High Performance"
|
|
179
|
+
features={['Lightning-fast response', '99.9% uptime SLA', 'Global CDN', 'Auto-scaling']}
|
|
180
|
+
topBgColor="#F59E0B"
|
|
181
|
+
/>
|
|
182
|
+
</div>
|
|
183
|
+
|
|
184
|
+
<style>
|
|
185
|
+
.services-grid {
|
|
186
|
+
display: grid;
|
|
187
|
+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
188
|
+
gap: 2rem;
|
|
189
|
+
}
|
|
190
|
+
</style>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Custom Branded Cards
|
|
194
|
+
|
|
195
|
+
```svelte
|
|
196
|
+
<IconFeatureCard
|
|
197
|
+
icon="/brand/premium-badge.svg"
|
|
198
|
+
iconAlt="Premium"
|
|
199
|
+
title="Premium Plan"
|
|
200
|
+
features={[
|
|
201
|
+
'Unlimited projects',
|
|
202
|
+
'Priority support',
|
|
203
|
+
'Advanced analytics',
|
|
204
|
+
'Custom integrations',
|
|
205
|
+
'Dedicated account manager'
|
|
206
|
+
]}
|
|
207
|
+
topBgColor="#6366F1"
|
|
208
|
+
iconBgColor="#EEF2FF"
|
|
209
|
+
titleColor="#4338CA"
|
|
210
|
+
featureColor="#4F46E5"
|
|
211
|
+
bulletColor="#818CF8"
|
|
212
|
+
iconSize="4.5rem"
|
|
213
|
+
iconContainerSize="6.5rem"
|
|
214
|
+
padding="2.5rem"
|
|
215
|
+
/>
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Compact Variant
|
|
219
|
+
|
|
220
|
+
```svelte
|
|
221
|
+
<IconFeatureCard
|
|
222
|
+
icon="/icons/basic.svg"
|
|
223
|
+
iconAlt="Basic"
|
|
224
|
+
title="Starter Plan"
|
|
225
|
+
features={['Up to 5 projects', 'Email support', 'Basic analytics']}
|
|
226
|
+
topBgColor="#64748B"
|
|
227
|
+
titleFontSize="1.5rem"
|
|
228
|
+
featureFontSize="1rem"
|
|
229
|
+
iconSize="3.5rem"
|
|
230
|
+
iconContainerSize="5rem"
|
|
231
|
+
padding="1.5rem"
|
|
232
|
+
featureGap="0.75rem"
|
|
233
|
+
/>
|
|
234
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as IconFeatureCard } from './IconFeatureCard.svelte';
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface ImageTextCardProps {
|
|
3
|
+
image: string;
|
|
4
|
+
imageAlt?: string;
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
bgColor?: string;
|
|
8
|
+
textColor?: string;
|
|
9
|
+
titleColor?: string;
|
|
10
|
+
descColor?: string;
|
|
11
|
+
imageSize?: string;
|
|
12
|
+
imageShape?: 'circle' | 'square' | 'rounded';
|
|
13
|
+
reverseLayout?: boolean;
|
|
14
|
+
cardHeight?: string;
|
|
15
|
+
padding?: string;
|
|
16
|
+
gap?: string;
|
|
17
|
+
titleFontSize?: string;
|
|
18
|
+
descFontSize?: string;
|
|
19
|
+
class?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let {
|
|
23
|
+
image,
|
|
24
|
+
imageAlt = '',
|
|
25
|
+
title,
|
|
26
|
+
description,
|
|
27
|
+
bgColor = '#B85C5C',
|
|
28
|
+
textColor = 'white',
|
|
29
|
+
titleColor,
|
|
30
|
+
descColor,
|
|
31
|
+
imageSize = '140px',
|
|
32
|
+
imageShape = 'circle',
|
|
33
|
+
reverseLayout = false,
|
|
34
|
+
cardHeight = 'auto',
|
|
35
|
+
padding = '3rem 4rem',
|
|
36
|
+
gap = '2.5rem',
|
|
37
|
+
titleFontSize = '2.25rem',
|
|
38
|
+
descFontSize = '1.25rem',
|
|
39
|
+
class: className = ''
|
|
40
|
+
}: ImageTextCardProps = $props();
|
|
41
|
+
|
|
42
|
+
const finalTitleColor = $derived(titleColor || textColor);
|
|
43
|
+
const finalDescColor = $derived(descColor || textColor);
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<div
|
|
47
|
+
class="image-text-card {className}"
|
|
48
|
+
class:reverse={reverseLayout}
|
|
49
|
+
style="
|
|
50
|
+
background-color: {bgColor};
|
|
51
|
+
height: {cardHeight};
|
|
52
|
+
padding: {padding};
|
|
53
|
+
gap: {gap};
|
|
54
|
+
color: {textColor};
|
|
55
|
+
"
|
|
56
|
+
>
|
|
57
|
+
<div class="image-container" style="width: {imageSize}; height: {imageSize};">
|
|
58
|
+
<img
|
|
59
|
+
src={image}
|
|
60
|
+
alt={imageAlt}
|
|
61
|
+
class="card-image"
|
|
62
|
+
class:circle={imageShape === 'circle'}
|
|
63
|
+
class:rounded={imageShape === 'rounded'}
|
|
64
|
+
class:square={imageShape === 'square'}
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<div class="text-content">
|
|
69
|
+
<h3 class="card-title" style="color: {finalTitleColor}; font-size: {titleFontSize};">
|
|
70
|
+
{title}
|
|
71
|
+
</h3>
|
|
72
|
+
<p class="card-description" style="color: {finalDescColor}; font-size: {descFontSize};">
|
|
73
|
+
{description}
|
|
74
|
+
</p>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<style>
|
|
79
|
+
.image-text-card {
|
|
80
|
+
display: flex;
|
|
81
|
+
align-items: center;
|
|
82
|
+
border-radius: 1.75rem;
|
|
83
|
+
transition: all 0.3s ease;
|
|
84
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
85
|
+
font-family: inherit;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.image-text-card:hover {
|
|
89
|
+
transform: translateY(-2px);
|
|
90
|
+
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.15);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.image-text-card.reverse {
|
|
94
|
+
flex-direction: row-reverse;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.image-container {
|
|
98
|
+
flex-shrink: 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.card-image {
|
|
102
|
+
width: 100%;
|
|
103
|
+
height: 100%;
|
|
104
|
+
object-fit: cover;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.card-image.circle {
|
|
108
|
+
border-radius: 50%;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.card-image.rounded {
|
|
112
|
+
border-radius: 1rem;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.card-image.square {
|
|
116
|
+
border-radius: 0;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.text-content {
|
|
120
|
+
flex: 1;
|
|
121
|
+
min-width: 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.card-title {
|
|
125
|
+
margin: 0 0 1rem 0;
|
|
126
|
+
font-weight: 700;
|
|
127
|
+
line-height: 1.2;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.card-description {
|
|
131
|
+
margin: 0;
|
|
132
|
+
line-height: 1.7;
|
|
133
|
+
font-weight: 400;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* Mobile: Stack vertically on tablets and below */
|
|
137
|
+
@media (max-width: 768px) {
|
|
138
|
+
.image-text-card {
|
|
139
|
+
flex-direction: column;
|
|
140
|
+
text-align: center;
|
|
141
|
+
gap: 2rem !important;
|
|
142
|
+
padding: 2rem !important;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.image-text-card.reverse {
|
|
146
|
+
flex-direction: column;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
</style>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
interface ImageTextCardProps {
|
|
2
|
+
image: string;
|
|
3
|
+
imageAlt?: string;
|
|
4
|
+
title: string;
|
|
5
|
+
description: string;
|
|
6
|
+
bgColor?: string;
|
|
7
|
+
textColor?: string;
|
|
8
|
+
titleColor?: string;
|
|
9
|
+
descColor?: string;
|
|
10
|
+
imageSize?: string;
|
|
11
|
+
imageShape?: 'circle' | 'square' | 'rounded';
|
|
12
|
+
reverseLayout?: boolean;
|
|
13
|
+
cardHeight?: string;
|
|
14
|
+
padding?: string;
|
|
15
|
+
gap?: string;
|
|
16
|
+
titleFontSize?: string;
|
|
17
|
+
descFontSize?: string;
|
|
18
|
+
class?: string;
|
|
19
|
+
}
|
|
20
|
+
declare const ImageTextCard: import("svelte").Component<ImageTextCardProps, {}, "">;
|
|
21
|
+
type ImageTextCard = ReturnType<typeof ImageTextCard>;
|
|
22
|
+
export default ImageTextCard;
|