@@ -223,6 +228,7 @@ function SuggestionResults({
{suggestion.hex}
@@ -274,15 +280,15 @@ function SuggestionResults({
{harmony.description}
-
- Mood
- - {harmony.mood}
+ - Common associations
+ - {harmony.commonAssociations}
- Examples
- {harmony.examples}
-
- Useful for
+ - Common applications
- {harmony.useCases.join(', ')}
diff --git a/frontend/src/components/ImageUpload.test.tsx b/frontend/src/components/ImageUpload.test.tsx
index f133d21..63fbdea 100644
--- a/frontend/src/components/ImageUpload.test.tsx
+++ b/frontend/src/components/ImageUpload.test.tsx
@@ -1,6 +1,7 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
-import ImageUpload, { MAX_IMAGE_BYTES } from './ImageUpload'
+import { MAX_IMAGE_BYTES } from '../limits'
+import ImageUpload, { validateImageFile } from './ImageUpload'
function imageFile(name = 'source.png', type = 'image/png') {
return new File(['image'], name, { type })
@@ -57,8 +58,29 @@ describe('ImageUpload', () => {
Object.defineProperty(oversized, 'size', { value: MAX_IMAGE_BYTES + 1 })
fireEvent.change(input, { target: { files: [oversized] } })
expect(await screen.findByRole('alert')).toHaveTextContent(
- 'Choose an image smaller than 15 MB.',
+ 'Choose an image that is 10 MB or smaller.',
)
expect(onImageSelected).not.toHaveBeenCalled()
})
+
+ it.each([
+ ['immediately below', MAX_IMAGE_BYTES - 1, null],
+ ['exactly at', MAX_IMAGE_BYTES, null],
+ [
+ 'immediately above',
+ MAX_IMAGE_BYTES + 1,
+ 'Choose an image that is 10 MB or smaller.',
+ ],
+ ])('validates a file %s the API limit', (_label, size, expected) => {
+ const file = imageFile()
+ Object.defineProperty(file, 'size', { value: size })
+ expect(validateImageFile(file)).toBe(expected)
+ })
+
+ it('shows the effective API limit', () => {
+ render(
)
+ expect(
+ screen.getByText('JPG, PNG, or WebP · up to 10 MB'),
+ ).toBeInTheDocument()
+ })
})
diff --git a/frontend/src/components/ImageUpload.tsx b/frontend/src/components/ImageUpload.tsx
index 2f7a6dd..4d26014 100644
--- a/frontend/src/components/ImageUpload.tsx
+++ b/frontend/src/components/ImageUpload.tsx
@@ -1,9 +1,9 @@
import { useRef, useState, type DragEvent, type KeyboardEvent } from 'react'
import { ImagePlus, Upload } from 'lucide-react'
+import { MAX_IMAGE_BYTES, MAX_IMAGE_MEGABYTES } from '../limits'
import Button from './ui/Button'
import Notice from './ui/Notice'
-export const MAX_IMAGE_BYTES = 15 * 1024 * 1024
const acceptedTypes = new Set(['image/jpeg', 'image/png', 'image/webp'])
export function validateImageFile(file: File): string | null {
@@ -15,7 +15,7 @@ export function validateImageFile(file: File): string | null {
return 'Choose a JPG, PNG, or WebP image.'
}
if (file.size > MAX_IMAGE_BYTES) {
- return 'Choose an image smaller than 15 MB.'
+ return `Choose an image that is ${MAX_IMAGE_MEGABYTES} MB or smaller.`
}
return null
}
@@ -103,7 +103,7 @@ export default function ImageUpload({
{dragReady ? 'Release to use this image' : 'Drop an image here'}
-
JPG, PNG, or WebP · up to 15 MB
+
JPG, PNG, or WebP · up to {MAX_IMAGE_MEGABYTES} MB