Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 185 additions & 0 deletions examples/Image-Search-App/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# Image Search App

A modern, responsive image search application that demonstrates API integration, asynchronous JavaScript, and responsive UI design concepts.

## 🚀 Features

- **Dynamic Image Search**: Search for images using keywords
- **Real-time Results**: Fetches and displays images instantly
- **Responsive Grid Layout**: Beautiful masonry-style grid that adapts to all screen sizes
- **Infinite Scroll**: Automatically loads more images as you scroll
- **Loading Indicators**: Visual feedback during API requests
- **Error Handling**: Comprehensive error handling for API failures and network issues
- **Full-size Image View**: Click any image to view it in full size with modal overlay
- **Modern UI**: Glass morphism design with smooth animations and transitions

## 🛠 Technologies Demonstrated

- **Fetch API & Async/Await**: Modern JavaScript for API requests
- **DOM Manipulation**: Dynamic content creation and updates
- **CSS Grid & Flexbox**: Responsive layout design
- **CSS Animations**: Smooth transitions and loading states
- **Event Handling**: Search, scroll, and click interactions
- **Error Handling**: Try-catch blocks and user-friendly error messages
- **Responsive Design**: Mobile-first approach with media queries

## 📁 Project Structure

Copy link

Copilot AI Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filename listed as styles.css but the actual file added is style.css; update the README to match the real filename to avoid confusion.

Copilot uses AI. Check for mistakes.
```
Image-Search-App/
├── index.html # Main HTML structure
├── styles.css # Responsive CSS with modern design
└── script.js # JavaScript logic and API integration
```

## 🔧 Setup Instructions

1. **Get Unsplash API Key**:
- Visit [Unsplash Developers](https://unsplash.com/developers)
- Create a free account and register your application
- Copy your Access Key

2. **Configure API Key**:
- Open `script.js`
- Replace `YOUR_UNSPLASH_ACCESS_KEY` with your actual API key:
```javascript
this.API_KEY = 'your_actual_api_key_here';
```

3. **Serve locally & open in browser**:
Modern browsers may block some fetch requests when opening files directly from disk. It's recommended to serve the folder with a simple static server and open http://localhost:8000.

Using Python 3 (recommended):
```bash
cd examples/Image-Search-App
python3 -m http.server 8000
# then open http://localhost:8000
```

Or use VS Code Live Server or `npx http-server`.

## 🎯 API Integration Details

The app uses the Unsplash Search Photos API:

```javascript
// Example API call structure
const response = await fetch('https://api.unsplash.com/search/photos', {
headers: {
'Authorization': `Client-ID ${API_KEY}`
}
});
```

**Parameters used:**
- `query`: Search term (e.g., "nature", "technology")
- `page`: Page number for pagination
- `per_page`: Number of results (12 per page)
- `orientation`: "landscape" for consistent layout

## 💡 Key Code Concepts

### Async/Await Pattern
```javascript
async performSearch(query) {
try {
const images = await this.fetchImages(query, page);
this.displayImages(images);
} catch (error) {
this.handleSearchError(error);
}
}
```

### Error Handling
```javascript
if (!response.ok) {
throw new Error(`API Error: ${response.status} ${response.statusText}`);
}
```

### Infinite Scroll Implementation
```javascript
shouldLoadMoreImages() {
const scrollTop = window.pageYOffset;
const windowHeight = window.innerHeight;
const documentHeight = document.documentElement.scrollHeight;

return scrollTop + windowHeight >= documentHeight - 1000;
}
```

### Responsive CSS Grid
Copy link

Copilot AI Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation shows minmax(280px, 1fr) and gap: 2rem, but the implemented CSS (style.css lines 56-59) uses minmax(240px, 1fr) and gap: var(--gap) (1.5rem). Align the README example with the actual code or note the difference intentionally.

Copilot uses AI. Check for mistakes.
```css
.image-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 2rem;
}
```

## 🎨 Responsive Design Features

- **Desktop**: 4-5 columns with larger images
- **Tablet**: 2-3 columns with medium images
- **Mobile**: Single column with optimized spacing
- **Touch-friendly**: Large buttons and touch targets
- **Performance**: Lazy loading and optimized images

## 🚨 Error Scenarios Handled

1. **Invalid API Key**: Clear message to configure API key
2. **Network Errors**: Retry functionality
3. **API Quota Exceeded**: Informative message about limits
4. **No Results Found**: Helpful suggestions for better search terms
5. **Empty Search Query**: Validation with user feedback

## 🔍 Search Suggestions

Try these search terms to see the app in action:
- nature
- technology
- animals
- architecture
- food
- travel
- abstract
- minimal

## 🌟 Bonus Features Implemented

✅ **Infinite Scroll**: Loads more images automatically
✅ **Loading Indicators**: Visual feedback during requests
✅ **Full-size Image Modal**: Click any image for larger view
✅ **Keyboard Navigation**: Enter to search, Escape to close modal
✅ **Smooth Animations**: Fade-in effects and hover states
✅ **Accessibility**: Proper focus states and ARIA attributes
Copy link

Copilot AI Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claim of 'Proper focus states and ARIA attributes' is not fully reflected in the current implementation (e.g., missing label for search input, no focus trap or restored focus in modal). Update the claim or implement the missing accessibility enhancements.

Suggested change
**Accessibility**: Proper focus states and ARIA attributes
**Accessibility**: Some focus states and ARIA attributes; further enhancements (e.g., search input label, modal focus trap) pending

Copilot uses AI. Check for mistakes.

## 📱 Browser Support

- Chrome (recommended)
- Firefox
- Safari
- Edge
- Modern mobile browsers

## 🔧 Customization

- Colors and styling in `style.css`
- API parameters in `script.js`
- Grid layout breakpoints
- Animation timings and effects

## 📚 Learning Outcomes

After studying this example, you'll understand:
- Modern JavaScript async patterns
- RESTful API integration
- Responsive CSS Grid layouts
- DOM manipulation techniques
- Error handling strategies
- UX/UI best practices

---

**Happy coding!** 🎉
84 changes: 84 additions & 0 deletions examples/Image-Search-App/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Image Search App</title>
<link rel="stylesheet" href="style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<div class="container">
<header class="header">
<h1 class="title">Image Search</h1>
<p class="subtitle">Discover amazing images from around the world</p>

<div class="search-container">
<div class="search-wrapper">
<svg class="search-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.35-4.35"></path>
</svg>
<input
type="text"
id="searchInput"
placeholder="Search for images... (e.g., nature, technology, animals)"
class="search-input"
autocomplete="off"
>
Comment on lines +24 to +30
Copy link

Copilot AI Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Input lacks an associated or an aria-label / aria-labelledby attribute; relying solely on placeholder impairs accessibility. Add a visible label or aria-label (e.g., <label for="searchInput">Search images) to improve screen reader support.

Copilot uses AI. Check for mistakes.
<button id="searchButton" class="search-button">
Search
</button>
</div>
</div>
</header>

<main class="main-content">
<div id="loadingIndicator" class="loading-indicator">
<div class="spinner"></div>
<p>Searching for images...</p>
</div>

<div id="errorMessage" class="error-message" style="display: none;">
<div class="error-content">
<svg class="error-icon" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"></circle>
<line x1="15" y1="9" x2="9" y2="15"></line>
<line x1="9" y1="9" x2="15" y2="15"></line>
</svg>
<h3>Oops! Something went wrong</h3>
<p id="errorText">Please check your internet connection and try again.</p>
<button id="retryButton" class="retry-button">Try Again</button>
</div>
</div>

<div id="noResults" class="no-results" style="display: none;">
<div class="no-results-content">
<svg class="no-results-icon" width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.35-4.35"></path>
<path d="M11 8a3 3 0 1 1 0 6"></path>
</svg>
<h3>No images found</h3>
<p>Try searching for something else or use different keywords.</p>
</div>
</div>

<div id="imageGrid" class="image-grid">
<!-- Images will be dynamically inserted here -->
</div>

<div id="loadMoreContainer" class="load-more-container" style="display: none;">
<button id="loadMoreButton" class="load-more-button">
<div class="load-more-spinner"></div>
Load More Images
</button>
Comment on lines +74 to +77
Copy link

Copilot AI Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The decorative spinner inside the button lacks aria-hidden and the button does not convey loading state via aria-busy or disabled contextually. Mark the spinner <div class="load-more-spinner" aria-hidden="true"> and toggle aria-busy / aria-live or provide status text for assistive technologies.

Suggested change
<button id="loadMoreButton" class="load-more-button">
<div class="load-more-spinner"></div>
Load More Images
</button>
<button id="loadMoreButton" class="load-more-button" aria-busy="false">
<div class="load-more-spinner" aria-hidden="true"></div>
Load More Images
</button>
<span id="loadMoreStatus" class="visually-hidden" aria-live="polite"></span>

Copilot uses AI. Check for mistakes.
</div>
</main>
</div>

<script src="script.js"></script>
</body>
</html>
Loading