Skip to content

Commit 3506fe8

Browse files
authored
feat: add element component (#5231)
Ref #3632 Here unflagged element component in components panel and html paste. Additionally - migrate link template to html element - added :local-link state to links which is replaced with [aria-current=page] when css is generated, sadly not yet supported in any browser - migrated many templates from legacy components to html elements - put tailwind paste behind flag
1 parent 4dfdf50 commit 3506fe8

File tree

20 files changed

+171
-94
lines changed

20 files changed

+171
-94
lines changed

apps/builder/app/builder/features/command-panel/command-panel.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import {
3939
} from "~/shared/nano-states";
4040
import {
4141
getComponentTemplateData,
42+
insertWebstudioElementAt,
4243
insertWebstudioFragmentAt,
4344
} from "~/shared/instance-utils";
4445
import { humanizeString } from "~/shared/string-utils";
@@ -165,9 +166,6 @@ const $componentOptions = computed(
165166
) {
166167
continue;
167168
}
168-
if (isFeatureEnabled("element") === false && name === elementComponent) {
169-
continue;
170-
}
171169

172170
const componentMeta = metas.get(name);
173171
const label =
@@ -207,9 +205,13 @@ const ComponentOptionsGroup = ({ options }: { options: ComponentOption[] }) => {
207205
value={component}
208206
onSelect={() => {
209207
closeCommandPanel();
210-
const fragment = getComponentTemplateData(component);
211-
if (fragment) {
212-
insertWebstudioFragmentAt(fragment);
208+
if (component === elementComponent) {
209+
insertWebstudioElementAt();
210+
} else {
211+
const fragment = getComponentTemplateData(component);
212+
if (fragment) {
213+
insertWebstudioFragmentAt(fragment);
214+
}
213215
}
214216
}}
215217
>

apps/builder/app/builder/features/components/components.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,6 @@ const $metas = computed(
101101
) {
102102
continue;
103103
}
104-
if (isFeatureEnabled("element") === false && name === elementComponent) {
105-
continue;
106-
}
107104

108105
availableComponents.add(name);
109106
metas.push({

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ const renderProperty = (
104104
},
105105
});
106106

107-
const forbiddenProperties = new Set(["style", "class", "className"]);
107+
const forbiddenProperties = new Set(["style"]);
108108

109109
const $availableProps = computed(
110110
[

apps/builder/app/builder/shared/commands.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
} from "@webstudio-is/sdk";
77
import type { Instance } from "@webstudio-is/sdk";
88
import { toast } from "@webstudio-is/design-system";
9+
import { isFeatureEnabled } from "@webstudio-is/feature-flags";
910
import { createCommandsEmitter, type Command } from "~/shared/commands-emitter";
1011
import {
1112
$editingItemSelector,
@@ -528,15 +529,19 @@ export const { emitCommand, subscribeCommands } = createCommandsEmitter({
528529
handler: () => unwrap(),
529530
},
530531

531-
{
532-
name: "pasteHtmlWithTailwindClasses",
533-
handler: async () => {
534-
const html = await navigator.clipboard.readText();
535-
let fragment = generateFragmentFromHtml(html);
536-
fragment = await generateFragmentFromTailwind(fragment);
537-
return insertWebstudioFragmentAt(fragment);
538-
},
539-
},
532+
...(isFeatureEnabled("tailwind")
533+
? [
534+
{
535+
name: "pasteHtmlWithTailwindClasses",
536+
handler: async () => {
537+
const html = await navigator.clipboard.readText();
538+
let fragment = generateFragmentFromHtml(html);
539+
fragment = await generateFragmentFromTailwind(fragment);
540+
return insertWebstudioFragmentAt(fragment);
541+
},
542+
},
543+
]
544+
: []),
540545

541546
// history
542547

apps/builder/app/shared/copy-paste/plugin-html.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1-
import { isFeatureEnabled } from "@webstudio-is/feature-flags";
21
import { generateFragmentFromHtml } from "../html";
32
import { insertWebstudioFragmentAt } from "../instance-utils";
43
import type { Plugin } from "./init-copy-paste";
54

65
export const html: Plugin = {
76
mimeType: "text/plain",
87
onPaste: (html: string) => {
9-
if (!isFeatureEnabled("element")) {
10-
return false;
11-
}
128
const fragment = generateFragmentFromHtml(html);
139
return insertWebstudioFragmentAt(fragment);
1410
},

packages/css-engine/src/core/atomic.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,23 @@ test("generate merged properties as single rule", () => {
279279
}"
280280
`);
281281
});
282+
283+
test("convert :local-link to [aria-current=page] selector", () => {
284+
const sheet = createRegularStyleSheet();
285+
const rule = sheet.addNestingRule(".instance");
286+
sheet.addMediaRule("x");
287+
rule.setDeclaration({
288+
breakpoint: "x",
289+
selector: ":local-link",
290+
property: "color",
291+
value: { type: "keyword", value: "green" },
292+
});
293+
expect(generateAtomic(sheet, { getKey: () => "" }).cssText)
294+
.toMatchInlineSnapshot(`
295+
"@media all {
296+
.c3mubaz[aria-current=page] {
297+
color: green
298+
}
299+
}"
300+
`);
301+
});

packages/css-engine/src/core/rules.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,11 @@ export class NestingRule {
258258
if (declaration.breakpoint !== breakpoint) {
259259
continue;
260260
}
261-
const { selector: nestedSelector } = declaration;
261+
let nestedSelector = declaration.selector;
262+
// polyfill :local-link with framework specific logic
263+
if (nestedSelector === ":local-link") {
264+
nestedSelector = "[aria-current=page]";
265+
}
262266
const selector = this.#selector + this.#descendantSuffix + nestedSelector;
263267
let style = styleBySelector.get(selector);
264268
if (style === undefined) {

packages/css-engine/src/core/style-sheet-regular.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,3 +765,19 @@ test("generate merged properties as single rule", () => {
765765
}"
766766
`);
767767
});
768+
769+
test("convert :local-link to [aria-current=page] selector", () => {
770+
const sheet = createRegularStyleSheet();
771+
const rule = sheet.addNestingRule(".instance");
772+
rule.setDeclaration({
773+
breakpoint: "base",
774+
selector: ":local-link",
775+
property: "color",
776+
value: { type: "keyword", value: "green" },
777+
});
778+
expect(rule.toString({ breakpoint: "base" })).toMatchInlineSnapshot(`
779+
".instance[aria-current=page] {
780+
color: green
781+
}"
782+
`);
783+
});

packages/feature-flags/src/flags.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ export const aiRadixComponents = false;
55
export const animation = false;
66
export const videoAnimation = false;
77
export const resourceProp = false;
8-
export const element = false;
8+
export const tailwind = false;

packages/html-data/src/pseudo-classes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const location = [
44
// ':link',
55
":visited",
66
// ':any-link',
7-
// ':local-link',
7+
":local-link",
88
// ':target',
99
// ':target-within',
1010
];

0 commit comments

Comments
 (0)