Files
RenewCMS/docs/design/source/media-field-tables.js
T

447 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export const tables = [
{
"title": "Media field: scope",
"tpl": "260px 140px minmax(0,1fr)",
"cols": [
"Screen or state",
"Scope",
"Note"
],
"rows": [
[
"2 Builder: media field selected, new, required",
"Available now",
"Needs the media type in the schema API."
],
[
"3 Review: refused and clean",
"Available now",
"The refusal is known to the client before the server answers."
],
[
"4 Field types: Media frame",
"Available now",
"The filter widget is Later: filtering on custom fields isn't in the API."
],
[
"5 Entry list: Thumbnail column, Columns menu, tooltip",
"Available now",
"Needs image summaries in the entry list payload."
],
[
"6 Entry editor: Media control, 10 states",
"Available now",
""
],
[
"10 Picker for fields, 8 states",
"Available now",
"Same endpoints as the article picker."
],
[
"11 Media library usage, 4 states",
"Available now",
"Needs entries in the usage endpoint."
],
[
"1 Schema list: custom type read-only view",
"Available now",
"Table only; the route is a decision, see conflicts."
],
[
"Several images in one field",
"Not drawn",
"Out of scope."
]
]
},
{
"title": "Media field: exact copy",
"tpl": "200px 200px minmax(0,1fr)",
"cols": [
"Surface",
"Element",
"Copy"
],
"rows": [
[
"Inspector",
"Hint",
"Holds one image from the media library. Entries link to the image instead of keeping a copy, so they always show its current version."
],
[
"Inspector",
"Locked type",
"Media · Can't change after saving."
],
[
"Inspector",
"Required",
"Required · An entry can't be saved with this field empty."
],
[
"Field row",
"Tag",
"Required"
],
[
"Review",
"Refusal row",
"Add Thumbnail · Can't be applied · Media, required. A media field can't have a default, so the 12 existing entries would have no image. Make Thumbnail optional to add it."
],
[
"Review",
"Clean row",
"Add Thumbnail · Media, optional. 12 entries are unaffected."
],
[
"Control",
"Empty",
"No image selected. · Pick an image"
],
[
"Control",
"Filled",
"lime-plaster-workshop.jpg · 1600 × 900 · 240 KB · Change image · Remove"
],
[
"Control",
"Help",
"One image from your library."
],
[
"Control",
"Error",
"Pick an image for Thumbnail."
],
[
"Control",
"Missing",
"This image is no longer in the library · Choose another image · Clear"
],
[
"Control",
"Missing help",
"Optional: You can still save. The entry keeps the link until you change it. Required: Thumbnail is required. Choose another image to save."
],
[
"Control",
"Announcements (live, polite)",
"Image selected: lime-plaster-workshop.jpg · Image removed from Thumbnail. · Thumbnail cleared."
],
[
"Read view",
"Rules cell",
"Optional · One image from the library"
],
[
"Gallery",
"Name, description",
"Media · One image from your media library"
],
[
"Picker",
"Title, search, row",
"Choose an image · Search by filename · No image · Leave this field empty."
],
[
"Picker",
"Badge and buttons",
"Current · Load more · Cancel · Use this image · Remove image (when No image is chosen)"
],
[
"Picker",
"States",
"Your library is empty · Images you upload appear here, ready to use in any article or entry. · Upload an image · Couldn't load your library · Check your connection and try again. · Try again"
],
[
"Entry list",
"Header, empty, missing",
"Thumbnail · – · Image no longer in the library"
],
[
"Media library",
"Badge and tooltip",
"Used in 3 · Used in entries: 3"
],
[
"Media library",
"Panel",
"Used in entries · and 2 more"
],
[
"Media library",
"Delete",
"Delete an image that's in use? · \"lime-plaster.jpg\" is used in 5 entries and 2 articles. Those entry fields will show \"This image is no longer in the library\", and the articles will show a broken image. This can't be undone. · Cancel · Delete image"
]
]
},
{
"title": "Media field: components, reused and new",
"tpl": "220px 140px minmax(0,1fr)",
"cols": [
"Component",
"Status",
"Notes"
],
"rows": [
[
"AppFrame, SchemaFrame builder rows, Insp, FRow, review dialog rows, entry form, entry list and Columns menu",
"Reused",
"The inspector hides Unique, default and limits for media, as it does for yes or no. One more type tile (seven)."
],
[
"MediaFrame: grid card, list row, detail panel, delete dialog, picker dialog",
"Reused",
"Picker gains a field mode (no alt text, no variant select, Current, No image). Panel gains a Used in entries list. Badge counts articles plus entries."
],
[
"MediaFieldControl",
"New (the only one)",
"Props: label, required, modelValue (image id or null), image (summary or missing), disabled, error. Emits update:modelValue. Opens the picker."
],
[
"Nuxt UI mapping",
"Nuxt UI v4",
"UFormField (label, help, error, required) · UButton \"Pick an image\", \"Change image\", \"Choose another image\" (outline) · UButton \"Remove\", \"Clear\" (ghost) · UModal on desktop and a bottom UDrawer on mobile for the picker, as the article picker · UTooltip in the list and on the badge · UIcon lucide:image, lucide:image-off, lucide:unlink. The thumbnail is a plain button."
]
]
},
{
"title": "Picker and field failures: status to copy",
"tpl": "160px minmax(0,1fr)",
"cols": [
"Request and status",
"Copy"
],
"rows": [
[
"GET /v1/media/ 400",
"That request wasn't valid. Check the fields and try again. (search is trimmed first, so this is rare)"
],
[
"GET /v1/media/ 401, 403",
"Global redirect, no local copy."
],
[
"GET /v1/media/ 429",
"Too many requests. Try again in a few minutes. (countdown alert as on the Media page)"
],
[
"GET /v1/media/ 500, network",
"Couldn't load your library · Check your connection and try again. · Try again (500 body: Something went wrong on our side. Nothing was changed. Try again in a moment.)"
],
[
"POST /v1/media/ 413",
"That file is too large."
],
[
"POST /v1/media/ 400",
"That request wasn't valid. Check the fields and try again."
],
[
"POST /v1/media/ 429",
"Too many requests. Try again in a few minutes."
],
[
"POST /v1/media/ 500, network",
"Something went wrong on our side. Nothing was changed. Try again in a moment."
],
[
"PUT entry 422 invalid_entry thumbnail: required",
"Pick an image for Thumbnail."
],
[
"PUT entry 422 invalid_entry thumbnail: type",
"Thumbnail must be an image from the library. (the image was deleted between the pick and the save)"
],
[
"PUT entry 409",
"This changed somewhere else. Reload and try again."
],
[
"DELETE /v1/media/{id} 404",
"That item no longer exists."
],
[
"DELETE /v1/media/{id} 500, network",
"Something went wrong on our side. Nothing was changed. Try again in a moment."
]
]
},
{
"title": "Row height with media",
"tpl": "220px minmax(0,1fr)",
"cols": [
"Surface",
"Choice and reason"
],
"rows": [
[
"Desktop table",
"The design rule is 48 px rows (56 px for the media library). The brief mentions 32 px, which the design does not use. The thumbnail is 40 px, so a 48 px row keeps 4 px above and below and does not grow. No row exceeds 48 px."
],
[
"Mobile card",
"Cards are 68 px minimum. The thumbnail is 32 px and leads the card. Cards do not grow."
],
[
"Missing image",
"Dashed square with the same 40 px (32 px) footprint, so the columns stay aligned and the row does not move."
]
]
},
{
"title": "Accessibility",
"tpl": "220px minmax(0,1fr)",
"cols": [
"Topic",
"Notes"
],
"rows": [
[
"Group and label",
"MediaFieldControl is role=\"group\" labelled by the field label. A required field adds aria-required to the control button and the * is part of the label text."
],
[
"Button names",
"Pick an image → \"Pick an image for Thumbnail\". Thumbnail button → \"Change image, lime-plaster-workshop.jpg, 1600 by 900, 240 KB\". Remove → \"Remove image from Thumbnail\". Clear → \"Clear Thumbnail\". Missing placeholder: role img, \"Image no longer in the library\". Each name starts with the visible label."
],
[
"Focus order",
"Label, thumbnail, Change image, Remove, help or error. The thumbnail duplicates Change image; if reviewers prefer one stop, make it tabindex -1 and keep the pointer shortcut."
],
[
"Announcements",
"One polite live region on the control: \"Image selected: lime-plaster-workshop.jpg\", \"Image removed from Thumbnail.\", \"Thumbnail cleared.\" No announcement when the picker opens."
],
[
"Focus after actions",
"Picker closes with Use this image: focus goes to Change image. Remove or Clear: focus goes to Pick an image. Cancel or Esc: focus returns to the button that opened it. Save refused: focus goes to the first invalid control (Pick an image or Choose another image)."
],
[
"Error",
"The error text has an id. The control button gets aria-invalid=\"true\" and aria-describedby set to the error id, then the help id. aria-invalid is not defined for group, so it sits on the focusable button."
],
[
"Picker",
"Tabs follow the existing tablist pattern. Tiles are buttons with aria-pressed and names like \"stone-steps.jpg, 310 KB\" and \", Current\". No image is a button with aria-pressed. Use this image uses aria-disabled while nothing is chosen. Load more keeps focus until new tiles arrive."
],
[
"Contrast and targets",
"Current badge is on-sand on sand (14.3). Text on selected tiles uses on-sand, never muted. The hover bar is inverted text on inverted ground (18.9). Dashed borders use border-accented (3.6). Mobile targets are 44 px."
],
[
"Motion and touch",
"No hover on mobile. Hover and focus never carry information alone."
]
]
},
{
"title": "Needs backend",
"tpl": "260px minmax(0,1fr)",
"cols": [
"Item",
"What is needed"
],
"rows": [
[
"Media field type",
"Schema API accepts type \"media\" with label, key, required only. The value is an image id or null. Writes with a missing id on a changed value return 422 invalid_entry, type."
],
[
"Image summary in entries",
"Entry and list responses include, per media field, filename, width, height, size and a small thumbnail URL, or a flag that the image is missing, so the editor and list need no extra requests."
],
[
"Usage by entries",
"GET /v1/media/{id}/usage returns articles and entries (content type name, key, entry id, title), a total count and the first few items."
],
[
"Counts for the badge and delete",
"GET /v1/media/ list items carry the combined use count. DELETE keeps working for used images; the entries keep their ids."
],
[
"Required with entries",
"The server refuses a new required media field on a type with entries with schema_incompatible. The client shows the refusal first."
]
]
},
{
"title": "Media field: conflicts with the existing design, decide before coding",
"tpl": "40px 260px minmax(0,1fr)",
"cols": [
"#",
"Brief",
"Existing design and what the board does"
],
"rows": [
[
"1",
"Rows follow a 32 px density rule.",
"Tables use 48 px rows (56 px for media) and 68 px cards. Drawn at 48 and 68; the 40 px thumbnail fits without growing a row."
],
[
"2",
"Thumbnail sits between Description and Starts on.",
"In the existing editor Description is the last field and Starts on comes second. Drawn after Description, at the end of the form, which is schema order. Moving it needs a different form order."
],
[
"3",
"\"Used in 3\" counts entries.",
"Today \"Used in N\" counts articles. Drawn as articles plus entries; the tooltip and the panel split them."
],
[
"4",
"Delete title \"Delete this image?\".",
"The existing dialog for an image in use is \"Delete an image that's in use?\" with an articles list. Kept that title and added the entries list. \"Delete this image?\" stays the unused-image title."
],
[
"5",
"\"Clear\" in the missing state.",
"The glossary says Remove detaches and the filled state uses Remove. Kept \"Clear\" as written. Suggest Remove for both."
],
[
"6",
"\"1600 x 900 - 240 KB\".",
"The design uses × and the middle dot (\"1600 × 900 · 240 KB\")."
],
[
"7",
"Refuse the required media field in the review step.",
"The review is informational and Apply changes is never disabled; the server decides. This one case is certain, so Apply is off. Alternative: leave Apply on and show the 422 refusal dialog."
],
[
"8",
"Primary button \"Use this image\".",
"The article picker says \"Insert image\". When No image is chosen the button reads \"Remove image\" (my addition). The picker keeps its existing copy for empty and failed states."
],
[
"9",
"Pick an image on empty optional fields too.",
"The brief names the button for required fields only. One name covers both."
],
[
"10",
"Read view of a custom type.",
"Only owners and admins see Schema, and they edit. No read-only route exists for custom types. Table drawn as the built-in one; the route is a decision."
],
[
"11",
"Thumbnail focus ring.",
"The thumbnail and Change image open the same picker, so there are two tab stops. See accessibility."
],
[
"12",
"Disabled look.",
"Entry form fields dim to 60% and foundations.md says 40%. The control follows the form."
],
[
"13",
"Picker page behind the dialog.",
"The existing picker frame shows the article editor. The field picker shows a stand-in for the entry form."
]
]
}
]