Add alt text to photo uploads
CI / Lint (pull_request) Successful in 53s
CI / Test (pull_request) Successful in 1m6s
Release Drafter / Update release notes draft (pull_request) Successful in 5s

- Form field for optionally adding a description
- Publish as `imeta` `alt`
- Render as `<img>` alt when set

Fixes a placeholder being published instead. Also strips the current
placeholder if set as alt text (for existing uploads).
This commit is contained in:
2026-08-07 07:25:53 -06:00
parent ac9870240f
commit 9807a2b822
7 changed files with 140 additions and 28 deletions
+4 -4
View File
@@ -237,7 +237,7 @@ export default class PhotoCarousel extends Component {
data-src={{photo.url}}
class="place-header-photo
{{if photo.isLandscape 'landscape' 'portrait'}}"
alt={{@name}}
alt={{photo.alt}}
{{fadeInImage photo.url}}
/>
{{else if this.isGalleryThumbnails}}
@@ -245,7 +245,7 @@ export default class PhotoCarousel extends Component {
data-src={{if photo.thumbUrl photo.thumbUrl photo.url}}
class="place-header-photo
{{if photo.isLandscape 'landscape' 'portrait'}}"
alt={{@name}}
alt={{photo.alt}}
{{fadeInImage (if photo.thumbUrl photo.thumbUrl photo.url)}}
/>
{{else}}
@@ -260,7 +260,7 @@ export default class PhotoCarousel extends Component {
<img
data-src={{photo.url}}
class="place-header-photo landscape"
alt={{@name}}
alt={{photo.alt}}
{{fadeInImage photo.url}}
/>
</picture>
@@ -269,7 +269,7 @@ export default class PhotoCarousel extends Component {
<img
data-src={{if photo.thumbUrl photo.thumbUrl photo.url}}
class="place-header-photo portrait"
alt={{@name}}
alt={{photo.alt}}
{{fadeInImage (if photo.thumbUrl photo.thumbUrl photo.url)}}
/>
{{/if}}
+30 -8
View File
@@ -27,6 +27,7 @@ export default class PlacePhotoUpload extends Component {
@tracked isPublishing = false;
@tracked isDragging = false;
@tracked selectedTags = [];
@tracked altText = '';
get place() {
return this.args.place || {};
@@ -103,6 +104,7 @@ export default class PlacePhotoUpload extends Component {
this.file = null;
this.uploadedPhoto = null;
this.selectedTags = [];
this.altText = '';
if (this.args.onUploadStateChange) {
this.args.onUploadStateChange(false);
}
@@ -118,6 +120,11 @@ export default class PlacePhotoUpload extends Component {
this.selectedTags = [tag];
}
@action
updateAltText(event) {
this.altText = event.target.value;
}
deletePhotoTask = task(async (photoData) => {
try {
if (photoData.hash) {
@@ -177,7 +184,10 @@ export default class PlacePhotoUpload extends Component {
imeta.push(`dim ${photo.dim}`);
}
imeta.push('alt A photo of a place');
const alt = this.altText.trim();
if (alt) {
imeta.push(`alt ${alt}`);
}
if (photo.fallbackUrls && photo.fallbackUrls.length > 0) {
for (const fallbackUrl of photo.fallbackUrls) {
@@ -209,6 +219,7 @@ export default class PlacePhotoUpload extends Component {
// Clear out the file so user can upload more or be done
this.file = null;
this.uploadedPhoto = null;
this.altText = '';
if (this.args.onUploadStateChange) {
this.args.onUploadStateChange(false);
@@ -235,13 +246,11 @@ export default class PlacePhotoUpload extends Component {
{{/if}}
{{#if this.file}}
<div class="photo-grid">
<PlacePhotoUploadItem
@file={{this.file}}
@onSuccess={{this.handleUploadSuccess}}
@onRemove={{this.removeFile}}
/>
</div>
<PlacePhotoUploadItem
@file={{this.file}}
@onSuccess={{this.handleUploadSuccess}}
@onRemove={{this.removeFile}}
/>
{{#if this.suggestedTags.length}}
<div class="photo-tag-suggestions">
@@ -263,6 +272,19 @@ export default class PlacePhotoUpload extends Component {
</div>
{{/if}}
<div class="form-group">
<label for="photo-alt-input">Description (optional):</label>
<input
id="photo-alt-input"
type="text"
class="form-control"
placeholder="Describe this photo"
value={{this.altText}}
disabled={{this.isPublishing}}
{{on "input" this.updateAltText}}
/>
</div>
<button
type="button"
class="btn btn-primary btn-publish"