feat(recipes): add location open and recipe ID copy to recipe modal

Add a de-emphasized meta footer to the recipe modal, mirroring the model
modal's hash footnote: a clickable file location on the left (opens the
recipe JSON via the generic open-file-location route, with the Docker
clipboard fallback) and a middle-truncated recipe ID with copy button on
the right.

The recipe detail API now exposes recipe_json_path so the frontend does
not have to guess the on-disk storage layout. Translations for the new
recipes.modal.* keys are filled in for all 9 locales, reusing the model
modal's openFileLocation wording per locale.
This commit is contained in:
Will Miao
2026-09-01 21:58:47 +08:00
parent 1fd7cc0123
commit 9584fa85c9
16 changed files with 665 additions and 2 deletions
+90
View File
@@ -1547,3 +1547,93 @@
width: 20px;
height: calc(1em * 1.3);
}
/* Meta footer: de-emphasized location + recipe ID line below the modal body,
mirroring the hash footnote in the shared model modal. Location sits left
(tail of the path survives truncation), ID + copy button sit right. */
.recipe-meta-footer {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding-top: 6px;
margin-top: 8px;
border-top: 1px solid var(--border-color);
font-size: 0.75em;
color: var(--text-muted);
}
.recipe-meta-footer[hidden] {
display: none;
}
.recipe-meta-location {
display: inline-flex;
align-items: center;
gap: 6px;
min-width: 0;
cursor: pointer;
}
.recipe-meta-location i {
flex-shrink: 0;
opacity: 0.6;
}
.recipe-meta-location-path {
font-family: var(--font-mono, monospace);
opacity: 0.7;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.recipe-meta-location:hover .recipe-meta-location-path,
.recipe-meta-location:focus-visible .recipe-meta-location-path {
opacity: 1;
text-decoration: underline;
}
.recipe-meta-location:focus-visible {
outline: 1px solid var(--lora-accent);
outline-offset: 2px;
border-radius: var(--border-radius-xs);
}
.recipe-meta-id {
display: inline-flex;
align-items: center;
gap: 6px;
flex-shrink: 0;
}
.recipe-meta-id-label {
font-size: 0.9em;
opacity: 0.5;
text-transform: uppercase;
letter-spacing: 0.03em;
}
.recipe-meta-id-value {
font-family: var(--font-mono, monospace);
opacity: 0.7;
white-space: nowrap;
}
.recipe-meta-copy-btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0 2px;
border: none;
background: none;
color: var(--text-muted);
opacity: 0.35;
font-size: 0.95em;
cursor: pointer;
flex-shrink: 0;
}
.recipe-meta-copy-btn:hover {
opacity: 0.9;
}