Skip to content

Commit 05a2dd2

Browse files
authored
feat: allow user to add asset description (#5369)
Ref #3263 Now users can control "alt" for all image uses with asset description. https://github.com/user-attachments/assets/c0e5ae4b-d2b0-4ec1-bf93-c385816369d1
1 parent 4f7eb26 commit 05a2dd2

File tree

7 files changed

+72
-51
lines changed

7 files changed

+72
-51
lines changed

apps/builder/app/builder/features/settings-panel/props-section/props-section.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ const renderProperty = (
101101
) {
102102
logic.handleChangeByPropName("width", propValue);
103103
logic.handleChangeByPropName("height", propValue);
104+
logic.handleChangeByPropName("alt", propValue);
104105
}
105106
},
106107
});

apps/builder/app/builder/shared/image-manager/image-info.tsx

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
CloudIcon,
3434
DimensionsIcon,
3535
GearIcon,
36+
InfoCircleIcon,
3637
PageIcon,
3738
TrashIcon,
3839
} from "@webstudio-is/icons";
@@ -200,7 +201,7 @@ const AssetUsagesList = ({ usages }: { usages: AssetUsage[] }) => {
200201
const UsageDot = styled(Box, {
201202
width: 6,
202203
height: 6,
203-
backgroundColor: theme.colors.foregroundDestructive,
204+
backgroundColor: "#000",
204205
border: "1px solid white",
205206
boxShadow: "0 0 3px rgb(0, 0, 0)",
206207
borderRadius: "50%",
@@ -287,6 +288,18 @@ const ImageInfoContent = ({
287288
});
288289
}
289290
);
291+
const [description, setDescription] = useLocalValue(
292+
asset.description ?? "",
293+
(newDescription) => {
294+
const assetId = asset.id;
295+
updateWebstudioData((data) => {
296+
const asset = data.assets.get(assetId);
297+
if (asset) {
298+
asset.description = newDescription;
299+
}
300+
});
301+
}
302+
);
290303

291304
const authPermit = useStore($authPermit);
292305

@@ -358,6 +371,27 @@ const ImageInfoContent = ({
358371
</InputErrorsTooltip>
359372
</Grid>
360373

374+
<Grid css={{ padding: theme.panel.padding, gap: 4 }}>
375+
<Label
376+
htmlFor="image-manager-description"
377+
css={{ display: "flex", alignItems: "center", gap: 4 }}
378+
>
379+
Description
380+
<Tooltip
381+
variant="wrapped"
382+
content="The description is used as the default “alt” text for the image."
383+
>
384+
<InfoCircleIcon />
385+
</Tooltip>
386+
</Label>
387+
<InputField
388+
id="image-manager-description"
389+
placeholder='Enter "alt" text'
390+
value={description}
391+
onChange={(event) => setDescription(event.target.value)}
392+
/>
393+
</Grid>
394+
361395
<Box css={{ padding: theme.panel.padding }}>
362396
{authPermit === "view" ? (
363397
<Tooltip side="bottom" content="View mode. You can't delete assets.">
@@ -376,9 +410,7 @@ const ImageInfoContent = ({
376410
) : (
377411
<Dialog>
378412
<DialogTrigger asChild>
379-
<Button color="destructive" prefix={<TrashIcon />}>
380-
Delete
381-
</Button>
413+
<Button>Review & delete</Button>
382414
</DialogTrigger>
383415
<DialogContent minWidth={360}>
384416
<DialogTitle>Delete asset?</DialogTitle>

apps/builder/app/shared/nano-states/props.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -259,20 +259,6 @@ export const $propValuesByInstanceSelector = computed(
259259

260260
if (props) {
261261
for (const prop of props) {
262-
if (prop.type === "asset" && prop.name === "width") {
263-
const asset = assets.get(prop.value);
264-
if (asset?.type === "image") {
265-
propValues.set("width", asset.meta.width);
266-
}
267-
}
268-
269-
if (prop.type === "asset" && prop.name === "height") {
270-
const asset = assets.get(prop.value);
271-
if (asset?.type === "image") {
272-
propValues.set("height", asset.meta.height);
273-
}
274-
}
275-
276262
// at this point asset and page either already converted to string
277263
// or can be ignored
278264
if (prop.type === "asset" || prop.type === "page") {

packages/asset-uploader/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
},
1212
"dependencies": {
1313
"@aws-crypto/sha256-js": "^5.2.0",
14-
"@smithy/signature-v4": "^5.0.1",
14+
"@smithy/signature-v4": "^5.1.3",
1515
"@webstudio-is/fonts": "workspace:*",
1616
"@webstudio-is/sdk": "workspace:*",
1717
"@webstudio-is/trpc-interface": "workspace:*",
@@ -22,7 +22,7 @@
2222
"warn-once": "^0.1.1"
2323
},
2424
"devDependencies": {
25-
"@types/fontkit": "^2.0.7",
25+
"@types/fontkit": "^2.0.8",
2626
"@webstudio-is/tsconfig": "workspace:*",
2727
"vitest": "^3.1.2",
2828
"zod": "^3.24.2"

packages/asset-uploader/src/utils/font-data.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,6 @@ import {
88
type FontStyle,
99
} from "@webstudio-is/fonts";
1010

11-
// @todo sumbit this to definitely typed, they are not up to date
12-
declare module "fontkit" {
13-
export interface Font {
14-
variationAxes: VariationAxes;
15-
}
16-
}
17-
1811
// same default fontkit uses internally
1912
const defaultLanguage = "en";
2013

packages/react-sdk/src/props.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ export const normalizeProps = ({
6060
continue;
6161
}
6262

63+
if (prop.name === "alt" && asset.type === "image") {
64+
newProps.push({
65+
...propBase,
66+
type: "string",
67+
value: asset.description ?? "",
68+
});
69+
continue;
70+
}
71+
6372
newProps.push({
6473
...propBase,
6574
type: "string",

pnpm-lock.yaml

Lines changed: 24 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)