Skip to content

Commit d294078

Browse files
authored
Merge pull request #161: fix: quick-ref CSS snippet meaningful values + slot styling guidance
fix: quick-ref CSS snippet meaningful values + slot styling guidance
2 parents f814f0b + 87a1c86 commit d294078

File tree

3 files changed

+66
-5
lines changed

3 files changed

+66
-5
lines changed

.changeset/enhance-quick-ref.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'helixir': patch
3+
'@helixir/core': patch
4+
---
5+
6+
fix: quick-ref CSS snippet uses meaningful values instead of misleading 'initial', adds slot styling guidance

packages/core/src/handlers/quick-ref.ts

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,22 +76,50 @@ function buildCssSnippet(tagName: string, meta: ComponentMetadata): string {
7676
if (meta.cssProperties.length > 0) {
7777
const propLines = meta.cssProperties
7878
.slice(0, 5)
79-
.map((p) => ` ${p.name}: initial;`)
79+
.map((p) => {
80+
const value = p.default ?? guessDefaultValue(p.name);
81+
return ` ${p.name}: ${value};`;
82+
})
8083
.join('\n');
81-
parts.push(`${tagName} {\n${propLines}\n}`);
84+
parts.push(`/* Token customization */\n${tagName} {\n${propLines}\n}`);
8285
}
8386

8487
if (meta.cssParts.length > 0) {
8588
const partBlocks = meta.cssParts
8689
.slice(0, 3)
8790
.map((p) => `${tagName}::part(${p.name}) {\n /* ${p.description || p.name} */\n}`)
8891
.join('\n\n');
89-
parts.push(partBlocks);
92+
parts.push(`/* Part-based customization */\n${partBlocks}`);
93+
}
94+
95+
if (meta.slots.length > 0) {
96+
const slotLines: string[] = [];
97+
const hasDefaultSlot = meta.slots.some((s) => s.name === '');
98+
const namedSlots = meta.slots.filter((s) => s.name !== '');
99+
100+
if (hasDefaultSlot) {
101+
slotLines.push(`${tagName} > * { /* default slot content */ }`);
102+
}
103+
for (const slot of namedSlots.slice(0, 3)) {
104+
slotLines.push(`${tagName} [slot="${slot.name}"] { /* ${slot.description || slot.name} */ }`);
105+
}
106+
107+
parts.push(`/* Slot styling — target in light DOM CSS */\n${slotLines.join('\n')}`);
90108
}
91109

92110
return parts.join('\n\n');
93111
}
94112

113+
function guessDefaultValue(propName: string): string {
114+
const lower = propName.toLowerCase();
115+
if (/color|bg|background/.test(lower)) return '#value';
116+
if (/size|font/.test(lower)) return '1rem';
117+
if (/radius/.test(lower)) return '4px';
118+
if (/spacing|padding|margin|gap/.test(lower)) return '1rem';
119+
if (/shadow/.test(lower)) return '0 1px 2px rgba(0,0,0,.1)';
120+
return '#value';
121+
}
122+
95123
// ─── Main Entry Point ───────────────────────────────────────────────────────
96124

97125
export function getComponentQuickRef(meta: ComponentMetadata): ComponentQuickRef {
@@ -131,7 +159,7 @@ export function getComponentQuickRef(meta: ComponentMetadata): ComponentQuickRef
131159
const cssProperties: QuickRefCssProperty[] = meta.cssProperties.map((p) => ({
132160
name: p.name,
133161
description: p.description,
134-
example: `${p.name}: initial;`,
162+
example: `${p.name}: ${p.default ?? guessDefaultValue(p.name)};`,
135163
}));
136164

137165
const cssParts: QuickRefCssPart[] = meta.cssParts.map((p) => ({

tests/handlers/quick-ref.test.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,12 @@ describe('getComponentQuickRef — attribute details', () => {
149149
// ─── CSS Styling Details ─────────────────────────────────────────────────────
150150

151151
describe('getComponentQuickRef — CSS details', () => {
152-
it('CSS properties include example usage', () => {
152+
it('CSS properties include example usage with meaningful value', () => {
153153
const ref = getComponentQuickRef(buttonMeta);
154154
const bg = ref.cssProperties.find((p) => p.name === '--my-button-bg');
155155
expect(bg?.example).toContain('--my-button-bg');
156+
// Should NOT use 'initial' — it's misleading for custom properties
157+
expect(bg?.example).not.toContain('initial');
156158
});
157159

158160
it('CSS parts include ::part() selector example', () => {
@@ -167,6 +169,31 @@ describe('getComponentQuickRef — CSS details', () => {
167169
expect(ref.cssSnippet).toContain('--my-button-bg');
168170
expect(ref.cssSnippet).toContain('::part(base)');
169171
});
172+
173+
it('cssSnippet does NOT use "initial" for custom property values', () => {
174+
const ref = getComponentQuickRef(buttonMeta);
175+
expect(ref.cssSnippet).not.toContain(': initial;');
176+
});
177+
178+
it('cssSnippet includes slot styling section when slots exist', () => {
179+
const ref = getComponentQuickRef(buttonMeta);
180+
expect(ref.cssSnippet).toContain('Slot styling');
181+
expect(ref.cssSnippet).toContain('[slot="prefix"]');
182+
});
183+
184+
it('cssSnippet omits slot styling for components without slots', () => {
185+
const ref = getComponentQuickRef(bareComponent);
186+
expect(ref.cssSnippet).not.toContain('Slot styling');
187+
});
188+
189+
it('CSS property example uses CEM default when available', () => {
190+
const metaWithDefault: ComponentMetadata = {
191+
...bareComponent,
192+
cssProperties: [{ name: '--my-bg', description: 'Background', default: '#fff' }],
193+
};
194+
const ref = getComponentQuickRef(metaWithDefault);
195+
expect(ref.cssProperties[0]?.example).toContain('#fff');
196+
});
170197
});
171198

172199
// ─── Bare Component ──────────────────────────────────────────────────────────

0 commit comments

Comments
 (0)