JordanJPatt/vibecoding1
0
1// Feature Card Web Component for VibeCoding12 3class FeatureCard extends HTMLElement {4 constructor() {5 super();6 this.attachShadow({ mode: 'open' });7 this.render();8 }9 10 static get observedAttributes() {11 return ['icon', 'title', 'description'];12 }13 14 attributeChangedCallback() {15 this.render();16 }17 18 render() {19 const icon = this.getAttribute('icon') || 'star';20 const title = this.getAttribute('title') || 'Feature Title';21 const description = this.getAttribute('description') || 'Feature description goes here.';22 23 this.shadowRoot.innerHTML = `24 <style>25 :host {26 display: block;27 transition: all 0.3s ease;28 }29 30 .card {31 background: var(--bg-primary, #ffffff);32 border: 1px solid var(--border-color, #e5e7eb);33 border-radius: 12px;34 padding: 24px;35 text-align: center;36 transition: all 0.3s ease;37 box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);38 height: 100%;39 display: flex;40 flex-direction: column;41 align-items: center;42 justify-content: center;43 }44 45 .card:hover {46 transform: translateY(-4px);47 box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);48 border-color: var(--primary-color, #3b82f6);49 }50 51 .icon-container {52 width: 64px;53 height: 64px;54 background: linear-gradient(135deg, var(--primary-color, #3b82f6), var(--secondary-color, #8b5cf6));55 border-radius: 16px;56 display: flex;57 align-items: center;58 justify-content: center;59 margin-bottom: 16px;60 transition: all 0.3s ease;61 }62 63 .card:hover .icon-container {64 transform: scale(1.1);65 }66 67 .icon {68 width: 32px;69 height: 32px;70 color: white;71 }72 73 .title {74 font-size: 1.25rem;75 font-weight: 600;76 color: var(--text-primary, #1f2937);77 margin-bottom: 8px;78 }79 80 .description {81 color: var(--text-secondary, #6b7280);82 line-height: 1.6;83 text-align: center;84 }85 86 @media (max-width: 768px) {87 .card {88 padding: 20px;89 }90 91 .icon-container {92 width: 56px;93 height: 56px;94 margin-bottom: 12px;95 }96 97 .icon {98 width: 28px;99 height: 28px;100 }101 102 .title {103 font-size: 1.125rem;104 }105 }106 </style>107 108 <div class="card">109 <div class="icon-container">110 <i data-feather="${icon}" class="icon"></i>111 </div>112 <h3 class="title">${title}</h3>113 <p class="description">${description}</p>114 </div>115 `;116 117 // Replace Feather icons if available118 if (typeof feather !== 'undefined') {119 feather.replace();120 }121 }122 123 connectedCallback() {124 // Component is now in the document125 this.render();126 }127}128 129// Register the custom element130customElements.define('feature-card', FeatureCard);131 132// Export for use in other scripts133if (typeof module !== 'undefined' && module.exports) {134 module.exports = FeatureCard;135}