Skip to content

Commit f892c66

Browse files
committed
Adding new component for card layout
1 parent d6963a9 commit f892c66

19 files changed

+1164
-1
lines changed

card-layout.html

Lines changed: 213 additions & 0 deletions
Large diffs are not rendered by default.

card-layout.js

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
// src/card-layout.js
2+
if (!document.getElementById("hind-fonts-card")) {
3+
const fontStyles = document.createElement("style");
4+
fontStyles.id = "hind-fonts-card";
5+
fontStyles.textContent = `
6+
@font-face {
7+
font-family: 'Hind';
8+
font-style: normal;
9+
font-weight: 400;
10+
font-display: swap;
11+
src: url('https://media.library.caltech.edu/cl-webcomponents/fonts/hind-400.woff') format('woff');
12+
}
13+
@font-face {
14+
font-family: 'Hind';
15+
font-style: normal;
16+
font-weight: 500;
17+
font-display: swap;
18+
src: url('https://media.library.caltech.edu/cl-webcomponents/fonts/hind-500.woff') format('woff');
19+
}
20+
@font-face {
21+
font-family: 'Hind';
22+
font-style: normal;
23+
font-weight: 600;
24+
font-display: swap;
25+
src: url('https://media.library.caltech.edu/cl-webcomponents/fonts/hind-600.woff') format('woff');
26+
}
27+
`;
28+
document.head.appendChild(fontStyles);
29+
}
30+
var CardLayout = class extends HTMLElement {
31+
constructor() {
32+
super();
33+
const shadow = this.attachShadow({ mode: "open" });
34+
const template = document.createElement("template");
35+
template.innerHTML = `
36+
<style>
37+
/* BASE STYLES */
38+
:host {
39+
display: block;
40+
font-family: 'Hind', sans-serif;
41+
font-size: 16px;
42+
}
43+
44+
:host, *, *::before, *::after {
45+
box-sizing: border-box;
46+
}
47+
48+
/* LAYOUT */
49+
.cards-container {
50+
display: flex;
51+
gap: 16px;
52+
flex-wrap: wrap;
53+
}
54+
55+
/* CARD STYLES */
56+
.card {
57+
flex: 1;
58+
min-width: 220px;
59+
background: #ffffff;
60+
border: 1px solid #e0e0e0;
61+
border-radius: 8px;
62+
padding: 16px;
63+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
64+
display: flex;
65+
flex-direction: column;
66+
}
67+
68+
/* CARD IMAGE */
69+
.card-image {
70+
width: 100%;
71+
height: auto;
72+
border-radius: 4px;
73+
margin-bottom: 12px;
74+
object-fit: cover;
75+
}
76+
77+
.card-image-placeholder {
78+
width: 100%;
79+
height: 120px;
80+
background: #f0f0f0;
81+
border-radius: 4px;
82+
margin-bottom: 12px;
83+
display: flex;
84+
align-items: center;
85+
justify-content: center;
86+
color: #999;
87+
font-size: 0.875em;
88+
}
89+
90+
/* CARD TITLE */
91+
.card-title {
92+
margin: 0 0 8px 0;
93+
font-size: 1.1em;
94+
font-weight: 600;
95+
color: #333;
96+
}
97+
98+
/* CARD DESCRIPTION */
99+
.card-description {
100+
margin: 0 0 12px 0;
101+
color: #666;
102+
line-height: 1.5;
103+
flex-grow: 1;
104+
}
105+
106+
/* CARD LINK */
107+
.card-link {
108+
color: #008080;
109+
text-decoration: none;
110+
font-size: 0.9em;
111+
font-weight: 600;
112+
}
113+
114+
.card-link:hover {
115+
text-decoration: underline;
116+
}
117+
118+
.card-link:focus-visible {
119+
outline: 2px solid #008080;
120+
outline-offset: 2px;
121+
}
122+
123+
/* RESPONSIVE */
124+
@media (max-width: 600px) {
125+
.cards-container {
126+
flex-direction: column;
127+
}
128+
129+
.card {
130+
min-width: 100%;
131+
}
132+
}
133+
</style>
134+
135+
<div class="cards-container">
136+
<div class="card" id="card1">
137+
<div class="card-image-placeholder">Image</div>
138+
<h3 class="card-title">Card One</h3>
139+
<p class="card-description">Add your content here.</p>
140+
<a class="card-link" href="#">Read more</a>
141+
</div>
142+
143+
<div class="card" id="card2">
144+
<div class="card-image-placeholder">Image</div>
145+
<h3 class="card-title">Card Two</h3>
146+
<p class="card-description">Add your content here.</p>
147+
<a class="card-link" href="#">Read more</a>
148+
</div>
149+
150+
<div class="card" id="card3">
151+
<div class="card-image-placeholder">Image</div>
152+
<h3 class="card-title">Card Three</h3>
153+
<p class="card-description">Add your content here.</p>
154+
<a class="card-link" href="#">Read more</a>
155+
</div>
156+
</div>
157+
`;
158+
shadow.appendChild(template.content.cloneNode(true));
159+
}
160+
connectedCallback() {
161+
for (let i = 1; i <= 3; i++) {
162+
this.setupCard(i);
163+
}
164+
}
165+
setupCard(cardNum) {
166+
const card = this.shadowRoot.getElementById(`card${cardNum}`);
167+
if (!card) return;
168+
const prefix = `card${cardNum}`;
169+
const imageUrl = this.getAttribute(`${prefix}-image`);
170+
const imageContainer = card.querySelector(".card-image-placeholder, .card-image");
171+
if (imageUrl && imageContainer) {
172+
const img = document.createElement("img");
173+
img.src = imageUrl;
174+
img.alt = this.getAttribute(`${prefix}-title`) || `Card ${cardNum}`;
175+
img.className = "card-image";
176+
imageContainer.replaceWith(img);
177+
}
178+
const title = this.getAttribute(`${prefix}-title`);
179+
const titleEl = card.querySelector(".card-title");
180+
if (title && titleEl) {
181+
titleEl.textContent = title;
182+
}
183+
const description = this.getAttribute(`${prefix}-description`);
184+
const descEl = card.querySelector(".card-description");
185+
if (description && descEl) {
186+
descEl.textContent = description;
187+
}
188+
const link = this.getAttribute(`${prefix}-link`);
189+
const linkText = this.getAttribute(`${prefix}-link-text`) || "Read more";
190+
const linkEl = card.querySelector(".card-link");
191+
if (linkEl) {
192+
if (link) {
193+
linkEl.href = link;
194+
linkEl.textContent = linkText;
195+
} else {
196+
linkEl.style.display = "none";
197+
}
198+
}
199+
}
200+
};
201+
customElements.define("card-layout", CardLayout);
202+
export {
203+
CardLayout
204+
};

card-layout.md

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# Card Layout
2+
3+
A three-card layout component for displaying featured content with images, titles, descriptions, and links.
4+
5+
[View Demo](demo_card-layout.html)
6+
7+
## Key Features
8+
9+
- **Fixed Three-Card Layout**: Displays exactly three cards in a responsive flexbox row
10+
- **Attribute-Based Content**: Configure each card via simple HTML attributes
11+
- **Responsive Design**: Cards stack automatically on smaller screens
12+
- **Encapsulated Styles**: Shadow DOM prevents style conflicts with your page
13+
- **Automatic Updates**: Once installed, the component receives updates when new versions are released
14+
15+
## Installing
16+
17+
```html
18+
<!-- Add the component -->
19+
<card-layout
20+
card1-title="Card One"
21+
card1-description="Your description here."
22+
card1-link="/page1"
23+
24+
card2-title="Card Two"
25+
card2-description="Another description."
26+
card2-link="/page2"
27+
28+
card3-title="Card Three"
29+
card3-description="Third description."
30+
card3-link="/page3"
31+
></card-layout>
32+
33+
<!-- Include the JavaScript -->
34+
<script type="module" src="https://media.library.caltech.edu/cl-webcomponents/card-layout.js"></script>
35+
```
36+
37+
## Basic Usage
38+
39+
At minimum, provide a title and description for each card:
40+
41+
```html
42+
<card-layout
43+
card1-title="Sherman Fairchild Library"
44+
card1-description="Study spaces, course reserves, and technology lending."
45+
card1-link="https://library.caltech.edu/locations/sfl"
46+
47+
card2-title="Caltech Archives"
48+
card2-description="Explore Caltech's rich history and scientific legacy."
49+
card2-link="https://library.caltech.edu/archives"
50+
51+
card3-title="Research Support"
52+
card3-description="Get help with data management, publishing, and more."
53+
card3-link="https://library.caltech.edu/publish"
54+
></card-layout>
55+
```
56+
57+
When no image is provided, a placeholder is displayed.
58+
59+
## Adding Images
60+
61+
Add images to each card using the `card[1-3]-image` attributes:
62+
63+
```html
64+
<card-layout
65+
card1-image="https://example.com/image1.jpg"
66+
card1-title="Digital Collections"
67+
card1-description="Browse digitized rare books, photographs, and manuscripts."
68+
card1-link="https://library.caltech.edu/archives/collections"
69+
70+
card2-image="https://example.com/image2.jpg"
71+
card2-title="Workshops & Events"
72+
card2-description="Join us for research skills workshops and special events."
73+
card2-link="https://library.caltech.edu/events"
74+
75+
card3-image="https://example.com/image3.jpg"
76+
card3-title="Course Reserves"
77+
card3-description="Access textbooks and materials for your courses."
78+
card3-link="https://library.caltech.edu/borrow/reserves"
79+
></card-layout>
80+
```
81+
82+
## Custom Link Text
83+
84+
By default, links display "Read more". Customize with `card[1-3]-link-text`:
85+
86+
```html
87+
<card-layout
88+
card1-title="Digital Collections"
89+
card1-description="Browse our digitized materials."
90+
card1-link="https://library.caltech.edu/archives/collections"
91+
card1-link-text="Explore collections"
92+
93+
card2-title="Workshops & Events"
94+
card2-description="Join us for upcoming events."
95+
card2-link="https://library.caltech.edu/events"
96+
card2-link-text="View calendar"
97+
98+
card3-title="Course Reserves"
99+
card3-description="Access course materials."
100+
card3-link="https://library.caltech.edu/borrow/reserves"
101+
card3-link-text="Find reserves"
102+
></card-layout>
103+
```
104+
105+
## Hiding Links
106+
107+
If you don't provide a `card[1-3]-link` attribute, the link will be hidden for that card:
108+
109+
```html
110+
<card-layout
111+
card1-title="Information Only"
112+
card1-description="This card has no link."
113+
114+
card2-title="With Link"
115+
card2-description="This card has a link."
116+
card2-link="/some-page"
117+
118+
card3-title="Also No Link"
119+
card3-description="Another card without a link."
120+
></card-layout>
121+
```
122+
123+
## Complete Example
124+
125+
Here's a fully configured card layout using all available options:
126+
127+
```html
128+
<card-layout
129+
card1-image="https://example.com/collections.jpg"
130+
card1-title="Digital Collections"
131+
card1-description="Browse digitized rare books, photographs, and manuscripts from Caltech's history."
132+
card1-link="https://library.caltech.edu/archives/collections"
133+
card1-link-text="Explore collections"
134+
135+
card2-image="https://example.com/events.jpg"
136+
card2-title="Workshops & Events"
137+
card2-description="Join us for research skills workshops, author talks, and special events."
138+
card2-link="https://library.caltech.edu/events"
139+
card2-link-text="View calendar"
140+
141+
card3-image="https://example.com/reserves.jpg"
142+
card3-title="Course Reserves"
143+
card3-description="Access textbooks, readings, and other materials for your courses."
144+
card3-link="https://library.caltech.edu/borrow/reserves"
145+
card3-link-text="Find reserves"
146+
></card-layout>
147+
```
148+
149+
## Attribute Reference
150+
151+
| Attribute | Description | Default |
152+
|-----------|-------------|---------|
153+
| `card[1-3]-image` | URL for the card image | Placeholder shown |
154+
| `card[1-3]-title` | Card heading text | "Card One/Two/Three" |
155+
| `card[1-3]-description` | Brief description text | "Add your content here." |
156+
| `card[1-3]-link` | URL for the link | Link hidden if not set |
157+
| `card[1-3]-link-text` | Custom text for the link | "Read more" |
158+
159+
Replace `[1-3]` with the card number (1, 2, or 3).
160+
161+
## Responsive Behavior
162+
163+
- **Desktop**: Cards display in a horizontal row with equal widths
164+
- **Mobile** (< 600px): Cards stack vertically, each taking full width
165+
166+
The component handles this automatically with no additional configuration needed.

0 commit comments

Comments
 (0)