Skip to content
Closed
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
4 changes: 4 additions & 0 deletions apps/web/public/assets/theme/graphite-theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -1868,6 +1868,10 @@ html[data-theme="dark"]:where([data-palette="graphite"]) .shell-openings-summary
border: 1px solid #dddddd;
}

:where(html[data-theme="dark"][data-palette="graphite"]) .shape-menu-item .shape-menu-thumb::after {
background: var(--shape-default-color);
}

:where(html[data-theme="dark"][data-palette="graphite"]) .shape-menu-dropdown:not(.sketch-shape-menu-dropdown) {
--shape-menu-columns: 4;
--shape-menu-width: calc(var(--shape-menu-columns) * 210px + (var(--shape-menu-columns) - 1) * 4px + 34px);
Expand Down
33 changes: 32 additions & 1 deletion apps/web/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -4750,6 +4750,37 @@ html[data-theme="dark"] .shell-openings-summary {
font-size: 0.85em;
}

/* The colour a library entry lands in: its own, or the colour its kind saves in the shape defaults.
The grey icon keeps its shading; a colour layer masked by the icon's outline multiplies over it. */
.shape-menu-item .shape-menu-thumb {
position: relative;
display: block;
flex: 0 0 auto;
width: 48px;
height: 48px;
max-width: none;
isolation: isolate;
pointer-events: none;
}

.shape-menu-item .shape-menu-thumb img {
display: block;
width: 48px;
height: 48px;
object-fit: contain;
}

.shape-menu-item .shape-menu-thumb::after {
content: "";
position: absolute;
inset: 0;
background: var(--shape-default-color);
-webkit-mask: var(--shape-icon) center / contain no-repeat;
mask: var(--shape-icon) center / contain no-repeat;
mix-blend-mode: multiply;
pointer-events: none;
}

/* Custom shapes above the basic shapes (#109). Both scroll together in the
menu body, so the library list itself no longer scrolls on its own there. */
.shape-menu-body {
Expand Down Expand Up @@ -4848,7 +4879,7 @@ html[data-simple-mode="on"]:not([data-toolbar-size]) .shape-menu-dropdown:not(.s
padding: 5px;
}

.shape-menu-icons-only .shape-menu-item > span:not(.my-shape-no-preview) {
.shape-menu-icons-only .shape-menu-item > span:not(.my-shape-no-preview):not(.shape-menu-thumb) {
display: none;
}

Expand Down
14 changes: 12 additions & 2 deletions apps/web/src/components/LayerlingEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ import {
type LylFileHandle,
} from "@/lib/lylFileAccess";
import { simplifyTrianglePositions } from "@/lib/meshSimplify";
import { clipboardShape, displayShapeName, iconTagAsset, qrCodeAsset, libraryShapeAssets, makeShapeFromAsset, nameTagAsset, shapeAssetLabel, shapeAssetMenuLabel, toolbarShapeAssets } from "@/lib/shapeCatalog";
import { clipboardShape, displayShapeName, iconTagAsset, qrCodeAsset, libraryShapeAssets, makeShapeFromAsset, nameTagAsset, shapeAssetColor, shapeAssetLabel, shapeAssetMenuLabel, toolbarShapeAssets } from "@/lib/shapeCatalog";
import { importedShapeFromStl } from "@/lib/stlImport";
import { exportMeshesToStl } from "@/lib/stlExport";
import { exportMeshesTo3mf, THREE_MF_MEDIA_TYPE } from "@/lib/threemfExport";
Expand Down Expand Up @@ -12511,6 +12511,7 @@ export function LayerlingEditor({
}
addShape(shape);
}}
shapeCustomizations={workspaceSettings.shapeCustomizations}
/>
<div className="editor-body">
{outlinerOpen ? (
Expand Down Expand Up @@ -13440,6 +13441,7 @@ function SecondaryToolbar({
overhangAngle,
onToggleOverhangs,
renderMyShapes,
shapeCustomizations,
objects,
onSelectObject,
}: {
Expand Down Expand Up @@ -13565,6 +13567,8 @@ function SecondaryToolbar({
onToggleOverhangs: () => void;
/** Custom shapes above the library; gets the way to close the menu. */
renderMyShapes?: (close: () => void) => ReactNode;
/** The shape defaults, so each library entry can show the colour it will be added in. */
shapeCustomizations: WorkplaneWorkspaceSettings["shapeCustomizations"];
/** The bodies of the design, so the command search can find them by name. */
objects: ReadonlyArray<{ id: string; name: string; kind: string; hidden: boolean }>;
onSelectObject: (id: string) => void;
Expand Down Expand Up @@ -14058,6 +14062,7 @@ function SecondaryToolbar({
type="button"
title={shapeAssetMenuLabel(shape).replace(/\s+/g, " ")}
aria-label={shapeAssetMenuLabel(shape).replace(/\s+/g, " ")}
style={{ "--shape-default-color": shapeAssetColor(shape, shapeCustomizations[shape.kind]) } as CSSProperties}
draggable
onClick={() => {
if (suppressNextShapeClickRef.current) {
Expand Down Expand Up @@ -14113,7 +14118,12 @@ function SecondaryToolbar({
}}
onDragEnd={closeShapesAfterPick}
>
<img src={shape.menuIcon} alt="" draggable={false} />
<span
className="shape-menu-thumb"
style={{ "--shape-icon": `url(/${shape.menuIcon.replace(/^\/+/, "")})` } as CSSProperties}
>
<img src={shape.menuIcon} alt="" draggable={false} />
</span>
<span className={shapeAssetMenuLabel(shape).split(/\s+/).some((word) => word.length > 13) ? "long-word" : undefined}>{shapeAssetMenuLabel(shape)}</span>
</button>
))}
Expand Down
11 changes: 10 additions & 1 deletion apps/web/src/lib/shapeCatalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,15 @@ export const qrCodeAsset: ToolbarShapeAsset = {
*/
export const libraryShapeAssets: ToolbarShapeAsset[] = toolbarShapeAssets.flatMap((asset) => (asset.id === "text" ? [asset, nameTagAsset, iconTagAsset, qrCodeAsset] : asset.id === "doubleCountersink" ? [] : [asset]));

/**
* The colour a new shape of this asset starts with: the asset's own, unless the shape
* defaults saved for its kind name another. The library shows the same colour beside each
* entry, so the list tells what will land on the workplane.
*/
export function shapeAssetColor(asset: ShapeAsset, customization: ShapeCustomization = {}): string {
return customization.color ?? asset.color;
}

/**
* Kinds a shape dragged from the library may have. Taken from the library
* itself: a hand-kept list here missed the rounded box and the ruler, and
Expand Down Expand Up @@ -865,7 +874,7 @@ export function makeShapeFromAsset(
id: createLocalId(asset.id),
name: asset.name,
kind: asset.kind,
color: customization.color ?? asset.color,
color: shapeAssetColor(asset, customization),
hole: asset.hole,
x: point?.x ?? 0,
z: point?.z ?? 0,
Expand Down
2 changes: 2 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ code still carries it - so a lower number further down is older, not newer.

## Unreleased

- **The shape library shows each shape in the colour it will be added in:** The pictures were grey, so the list said nothing about the colour that landed on the workplane. Every entry now wears the colour a new shape of it starts with - the catalogue's own, or the one saved for its kind under Shape defaults - so a red box, an orange cylinder and a blue sphere are recognisable before the click. The grey render keeps its shading: a colour layer, masked by the picture's outline, multiplies over it, in the list, in the icon-only size and in both themes. `shapeAssetColor` in `shapeCatalog.ts` is the one place that decides the colour, shared with `makeShapeFromAsset`; unit tests in `shapeCatalog.test.ts`; checked in the dev server in light, dark and icon-only menu.

## 1.99.0

- **Rounded box radii to 0.01 mm (#705):** `normalizeCornerFillet` and `normalizeTopBottomFillet` rounded to a tenth of a millimetre, so a corner fillet of 0.25 mm came back as 0.3 mm. They round to a hundredth now, and the fields (the shape's properties and the defaults in the workspace settings) step by 0.05. The CAD solid reads the same functions, so it follows. Unit test in `roundedBoxGeometry.test.ts` (0.25 stays 0.25, 7.336 becomes 7.34). Reported by @Algotz on GitHub.
Expand Down
16 changes: 15 additions & 1 deletion tests/unit/shapeCatalog.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";
import type { ShapeAsset } from "@/types/layerling";
import { clipboardShape, makeShapeFromAsset, parseDroppedShapeAsset, sceneShape, toolbarShapeAssets } from "@/lib/shapeCatalog";
import { clipboardShape, makeShapeFromAsset, parseDroppedShapeAsset, sceneShape, shapeAssetColor, toolbarShapeAssets } from "@/lib/shapeCatalog";

describe("shape catalog", () => {
it("exposes roundedBox directly after box in the toolbar catalog", () => {
Expand Down Expand Up @@ -330,3 +330,17 @@ describe("clipboardShape (#642)", () => {
expect(clipboardShape("box")).toBeNull();
});
});

describe("the colour the library shows", () => {
const box = toolbarShapeAssets.find((asset) => asset.id === "box")!;

it("is the asset's own until the shape defaults name another", () => {
expect(shapeAssetColor(box)).toBe(box.color);
expect(shapeAssetColor(box, { color: "#123456" })).toBe("#123456");
});

it("is the same colour the shape is added in", () => {
expect(makeShapeFromAsset(box).color).toBe(box.color);
expect(makeShapeFromAsset(box, undefined, { color: "#123456" }).color).toBe("#123456");
});
});