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
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
Expand Down Expand Up @@ -107,6 +108,10 @@ private fun ItemInfo(item: ClothingItem) {
color = WornColors.TextPrimary,
fontSize = 14.sp,
fontWeight = FontWeight.Medium,
// AI-generated names can run long; left unbounded they push the category row down and
// misalign the cards next to them in the grid row.
maxLines = 2,
overflow = TextOverflow.Ellipsis,
)
Row(
verticalAlignment = Alignment.CenterVertically,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,8 @@ private fun ItemSelectionGrid(

private val cellShape = RoundedCornerShape(16.dp)


// The cell is the photo alone: a name label here only ever sat on top of the garment, where it was
// unreadable. The photo carries the item's name as its content description for screen readers.
@Composable
private fun SelectableItemCell(
item: ClothingItem,
Expand All @@ -241,6 +242,7 @@ private fun SelectableItemCell(
modifier = modifier
.fillMaxWidth()
.height(100.dp)
.testTag("outfit_item_cell")
.clip(cellShape)
.border(
width = if (isSelected) 2.dp else 1.dp,
Expand All @@ -250,13 +252,6 @@ private fun SelectableItemCell(
.clickable(onClick = onClick),
) {
ItemThumbnail(item = item)
Text(
text = item.name,
color = WornColors.TextPrimary,
fontSize = 10.sp,
fontWeight = FontWeight.Medium,
modifier = Modifier.align(Alignment.BottomStart).padding(start = 12.dp, bottom = 8.dp),
)
SelectionIndicator(isSelected = isSelected, size = 20.dp, iconSize = 12.dp, modifier = Modifier.padding(8.dp))
}
}
Expand Down
4 changes: 4 additions & 0 deletions iosApp/iosApp/Components/ClothingCard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,13 @@ struct ClothingCard: View {

private var itemInfo: some View {
VStack(alignment: .leading, spacing: 2) {
// AI-generated names can run long; left unbounded they push the category row down and
// misalign the cards next to them in the grid row.
Text(item.name)
.font(.system(size: 14, weight: .medium))
.foregroundColor(WornColors.textPrimary)
.lineLimit(2)
.truncationMode(.tail)

HStack(spacing: 6) {
Circle()
Expand Down
13 changes: 3 additions & 10 deletions iosApp/iosApp/Screens/CreateOutfitSheet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ private struct SelectableItemCell: View {
let isSelected: Bool
let onTap: () -> Void

// The cell is the photo alone: a name label here only ever sat on top of the garment, where it
// was unreadable. The photo carries the item's name as its accessibility label.
var body: some View {
ZStack(alignment: .topLeading) {
StoredPhotoImage(path: item.photoPath) { placeholderIcon }
Expand All @@ -139,18 +141,9 @@ private struct SelectableItemCell: View {

SelectionIndicator(isSelected: isSelected, size: 20, iconSize: 10)
.padding(8)

VStack {
Spacer()
Text(item.name)
.font(.system(size: 10, weight: .medium))
.foregroundColor(WornColors.textPrimary)
.padding(.horizontal, 12)
.padding(.bottom, 8)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
.frame(height: 100)
.accessibilityIdentifier("outfit_item_cell")
.onTapGesture(perform: onTap)
}

Expand Down
6 changes: 4 additions & 2 deletions journeys/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ disambiguate.

## Preconditions

These journeys assume a **fresh install**: an empty wardrobe, no saved outfits, and no credentials
configured (neither the Claude API key nor YouCam try-on credentials, and no saved model photo).
Except where a journey's own `<description>` says otherwise — `outfit-item-grid.xml` needs a
populated wardrobe — these journeys assume a **fresh install**: an empty wardrobe, no saved outfits,
and no credentials configured (neither the Claude API key nor YouCam try-on credentials, and no saved model photo).
That state exercises the empty-state and locked flows without needing a real photo, network access,
or credentials. Journeys that would require capturing a photo or calling an external API stop at the
point where that external input is needed and verify the UI is in the expected state.
Expand Down Expand Up @@ -72,6 +73,7 @@ described above are unavailable on this path, so fall back to the visible text a
| `remove-background.xml` | Verify the Add-item "Remove background" toggle is gated on a photo being present (absent until one is chosen). |
| `crop-photo.xml` | Verify the Add-item "Crop" button is gated on a photo being present (absent until one is chosen). |
| `create-first-outfit.xml` | From the empty Outfits tab, open the Create-outfit sheet. |
| `outfit-item-grid.xml` | Verify the Create-outfit item grid shows photo-only cells and selects on tap. Needs a populated wardrobe. |
| `connect-api-key.xml` | Open Settings and reach the Claude API key entry sheet. |
| `connect-youcam.xml` | Open Settings and reach the YouCam try-on credentials sheet. |
| `edit-profile.xml` | Open Settings and reach the Your-Profile sheet with its chip groups. |
Expand Down
30 changes: 30 additions & 0 deletions journeys/outfit-item-grid.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<journey name="Outfit item grid">
<description>
Opens the Create-outfit sheet over a populated wardrobe and verifies the item selection grid
shows photo-only cells with no name text over the garment, and that tapping a cell selects
it. Start state: the wardrobe contains at least two items, one with a long name.
</description>
<actions>
<action>
Tap the "OUTFITS" tab in the bottom navigation bar.
</action>
<action>
Tap the "Create" button in the Outfits screen header.
</action>
<action>
Verify the "Create outfit" sheet is shown with an "Outfit name (optional)" field and a
"Select items" section.
</action>
<action>
Verify each item in the selection grid shows only its photo and a selection indicator,
with no item name text drawn over the photo.
</action>
<action>
Tap the first item in the selection grid.
</action>
<action>
Verify the "Select items" header shows "1 selected" and the tapped item shows a filled
selection indicator.
</action>
</actions>
</journey>
Loading