UNPKG

story-az-card-kit

Version:

A flexible and customizable story card component with multiple layouts

173 lines (146 loc) 4.93 kB
/** * Creates a story card element for vanilla JavaScript usage * @param {Object} options - Story card configuration * @param {string} options.title - Card title * @param {string} options.description - Card description * @param {string} options.image - Image URL * @param {string} options.author - Author name * @param {string} options.date - Publication date * @param {string[]} options.tags - Array of tags * @param {string} options.layout - Layout type (vertical, horizontal, etc.) * @param {string} options.theme - Theme type (default, dark, minimal, etc.) * @param {Function} options.onClick - Click handler function * @param {string} options.className - Additional CSS classes * @returns {HTMLElement} - The created story card element */ export const createStoryCard = (options = {}) => { const { title, description, image, author, date, tags = [], layout = 'vertical', theme = 'default', onClick, className = '' } = options; const card = document.createElement('div'); const baseClass = 'story-card'; const layoutClass = `story-card--${layout}`; const themeClass = `story-card--${theme}`; const cardClasses = [ baseClass, layoutClass, themeClass, className ].filter(Boolean).join(' '); card.className = cardClasses; card.setAttribute('role', 'button'); card.setAttribute('tabindex', '0'); // Create image section if (image) { const imageContainer = document.createElement('div'); imageContainer.className = 'story-card__image'; const img = document.createElement('img'); img.src = image; img.alt = title || ''; img.loading = 'lazy'; imageContainer.appendChild(img); card.appendChild(imageContainer); } // Create content section const content = document.createElement('div'); content.className = 'story-card__content'; // Add title if (title) { const titleElement = document.createElement('h3'); titleElement.className = 'story-card__title'; titleElement.textContent = title; content.appendChild(titleElement); } // Add description if (description) { const descriptionElement = document.createElement('p'); descriptionElement.className = 'story-card__description'; descriptionElement.textContent = description; content.appendChild(descriptionElement); } // Add meta information if (author || date) { const meta = document.createElement('div'); meta.className = 'story-card__meta'; if (author) { const authorElement = document.createElement('span'); authorElement.className = 'story-card__author'; authorElement.textContent = author; meta.appendChild(authorElement); } if (date) { const dateElement = document.createElement('time'); dateElement.className = 'story-card__date'; dateElement.setAttribute('datetime', date); dateElement.textContent = new Date(date).toLocaleDateString(); meta.appendChild(dateElement); } content.appendChild(meta); } // Add tags if (tags.length > 0) { const tagsContainer = document.createElement('div'); tagsContainer.className = 'story-card__tags'; tags.forEach(tag => { const tagElement = document.createElement('span'); tagElement.className = 'story-card__tag'; tagElement.textContent = tag; tagsContainer.appendChild(tagElement); }); content.appendChild(tagsContainer); } card.appendChild(content); // Add event listeners if (onClick) { card.addEventListener('click', (e) => { onClick(e, { title, description, image, author, date, tags }); }); card.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onClick(e, { title, description, image, author, date, tags }); } }); } return card; }; /** * Creates multiple story cards and returns them as an array * @param {Array} stories - Array of story configurations * @returns {HTMLElement[]} - Array of created story card elements */ export const createStoryCards = (stories = []) => { return stories.map(story => createStoryCard(story)); }; /** * Creates a grid container with story cards * @param {Array} stories - Array of story configurations * @param {Object} options - Grid options * @returns {HTMLElement} - Grid container with story cards */ export const createStoryCardGrid = (stories = [], options = {}) => { const { columns = 3, gap = 'medium', className = '' } = options; const grid = document.createElement('div'); const gridClass = `story-card-grid story-card-grid--${columns}-cols story-card-grid--gap-${gap}`; const gridClasses = [ gridClass, className ].filter(Boolean).join(' '); grid.className = gridClasses; const cards = createStoryCards(stories); cards.forEach(card => grid.appendChild(card)); return grid; };