rebly-sections 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/data/animations.csv +29 -0
- package/assets/data/component-library/features-grid.liquid +159 -25
- package/assets/data/component-library/hero-banner.liquid +166 -53
- package/assets/data/component-library/image-gallery.liquid +160 -32
- package/assets/data/component-library/pricing-table.liquid +224 -36
- package/assets/data/component-library/testimonials-slider.liquid +216 -46
- package/assets/data/design-tokens.csv +42 -0
- package/assets/scripts/core.py +7 -1
- package/assets/scripts/quality-gate-design-checks.py +101 -0
- package/assets/scripts/quality-gate.py +31 -0
- package/assets/scripts/section-generator.py +20 -31
- package/assets/scripts/ux-bridge.py +197 -0
- package/assets/templates/generation-prompt.md +5 -1
- package/package.json +1 -1
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""UX Bridge - Deep ui-ux-pro-max integration for design system, animations, UX guidelines."""
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
import importlib.util
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
_scripts_dir = str(Path(__file__).parent)
|
|
11
|
+
if _scripts_dir not in sys.path:
|
|
12
|
+
sys.path.append(_scripts_dir)
|
|
13
|
+
|
|
14
|
+
_UX_CANDIDATES = [
|
|
15
|
+
Path(__file__).parent.parent.parent.parent / ".claude" / "skills" / "ui-ux-pro-max" / "scripts",
|
|
16
|
+
Path.home() / ".claude" / "skills" / "ui-ux-pro-max" / "scripts",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
# Static animation guidelines — always included, no external dependency
|
|
20
|
+
_ANIMATION_GUIDELINES = (
|
|
21
|
+
" <animation_guidelines>\n"
|
|
22
|
+
" <timing>\n"
|
|
23
|
+
" <rule>Micro-interactions: 50-100ms</rule>\n"
|
|
24
|
+
" <rule>Standard hover: 150-300ms</rule>\n"
|
|
25
|
+
" <rule>Complex animations: 400-600ms</rule>\n"
|
|
26
|
+
" </timing>\n"
|
|
27
|
+
" <performance>\n"
|
|
28
|
+
" <rule>Always use transform/opacity (GPU-accelerated)</rule>\n"
|
|
29
|
+
" <rule>Always include prefers-reduced-motion media query</rule>\n"
|
|
30
|
+
" <rule>Use Intersection Observer for scroll-triggered animations</rule>\n"
|
|
31
|
+
" <rule>No external JS dependencies — Shopify-native only</rule>\n"
|
|
32
|
+
" </performance>\n"
|
|
33
|
+
" </animation_guidelines>"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _load_module(path: Path, name: str, extra_sys_path: Optional[str] = None) -> Optional[object]:
|
|
38
|
+
"""Load a Python module from an absolute path via importlib."""
|
|
39
|
+
if not path.exists():
|
|
40
|
+
return None
|
|
41
|
+
try:
|
|
42
|
+
if extra_sys_path and extra_sys_path not in sys.path:
|
|
43
|
+
sys.path.insert(0, extra_sys_path)
|
|
44
|
+
spec = importlib.util.spec_from_file_location(name, path)
|
|
45
|
+
mod = importlib.util.module_from_spec(spec)
|
|
46
|
+
spec.loader.exec_module(mod)
|
|
47
|
+
return mod
|
|
48
|
+
except Exception:
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _find_ux_skill() -> Optional[Path]:
|
|
53
|
+
"""Return first valid ui-ux-pro-max scripts directory found."""
|
|
54
|
+
for candidate in _UX_CANDIDATES:
|
|
55
|
+
if (candidate / "core.py").exists():
|
|
56
|
+
return candidate
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _build_design_system_xml(keywords: str, scripts_path: Path) -> str:
|
|
61
|
+
"""Build <design_system_context> XML via design_system.py or fallback searches."""
|
|
62
|
+
try:
|
|
63
|
+
sp = str(scripts_path)
|
|
64
|
+
ds_mod = _load_module(scripts_path / "design_system.py", "ux_design_system", sp)
|
|
65
|
+
if ds_mod and hasattr(ds_mod, "DesignSystemGenerator"):
|
|
66
|
+
gen = ds_mod.DesignSystemGenerator()
|
|
67
|
+
ds = gen.generate(keywords)
|
|
68
|
+
style = ds.get("style", {})
|
|
69
|
+
colors = ds.get("colors", {})
|
|
70
|
+
typo = ds.get("typography", {})
|
|
71
|
+
effects = ds.get("key_effects", "")
|
|
72
|
+
lines = [
|
|
73
|
+
"<design_system_context>",
|
|
74
|
+
"**Recommended Design System:**",
|
|
75
|
+
"",
|
|
76
|
+
f"**Style:** {style.get('name', '')} — {style.get('keywords', '')}",
|
|
77
|
+
f" Effects: {style.get('effects', effects)}",
|
|
78
|
+
f" Performance: {style.get('performance', '')} | Accessibility: {style.get('accessibility', '')}",
|
|
79
|
+
"",
|
|
80
|
+
"**Colors:**",
|
|
81
|
+
f" Primary: {colors.get('primary', '')} | Secondary: {colors.get('secondary', '')} | CTA: {colors.get('cta', '')}",
|
|
82
|
+
f" Background: {colors.get('background', '')} | Text: {colors.get('text', '')}",
|
|
83
|
+
"",
|
|
84
|
+
f"**Typography:** {typo.get('heading', '')} / {typo.get('body', '')}",
|
|
85
|
+
f" Mood: {typo.get('mood', '')}",
|
|
86
|
+
f" Google Fonts: {typo.get('google_fonts_url', '')}",
|
|
87
|
+
"",
|
|
88
|
+
f"**Key Effects:** {effects}",
|
|
89
|
+
"</design_system_context>",
|
|
90
|
+
]
|
|
91
|
+
return "\n".join(lines)
|
|
92
|
+
|
|
93
|
+
# Fallback: individual domain searches via ux core
|
|
94
|
+
ux_mod = _load_module(scripts_path / "core.py", "ux_core")
|
|
95
|
+
if not ux_mod or not hasattr(ux_mod, "search"):
|
|
96
|
+
return ""
|
|
97
|
+
|
|
98
|
+
style_r = ux_mod.search(keywords, domain="style", max_results=2)
|
|
99
|
+
color_r = ux_mod.search(keywords, domain="color", max_results=1)
|
|
100
|
+
typo_r = ux_mod.search(keywords, domain="typography", max_results=1)
|
|
101
|
+
|
|
102
|
+
style = (style_r.get("results") or [{}])[0]
|
|
103
|
+
color = (color_r.get("results") or [{}])[0]
|
|
104
|
+
typo = (typo_r.get("results") or [{}])[0]
|
|
105
|
+
|
|
106
|
+
lines = [
|
|
107
|
+
"<design_system_context>",
|
|
108
|
+
"**Recommended Design System:**",
|
|
109
|
+
"",
|
|
110
|
+
f"**Style:** {style.get('Style Category', '')} — {style.get('Keywords', '')}",
|
|
111
|
+
f" Effects: {style.get('Effects & Animation', '')}",
|
|
112
|
+
f" Performance: {style.get('Performance', '')} | Accessibility: {style.get('Accessibility', '')}",
|
|
113
|
+
"",
|
|
114
|
+
"**Colors:**",
|
|
115
|
+
f" Primary: {color.get('Primary (Hex)', '')} | Secondary: {color.get('Secondary (Hex)', '')} | CTA: {color.get('CTA (Hex)', '')}",
|
|
116
|
+
f" Background: {color.get('Background (Hex)', '')} | Text: {color.get('Text (Hex)', '')}",
|
|
117
|
+
"",
|
|
118
|
+
f"**Typography:** {typo.get('Heading Font', '')} / {typo.get('Body Font', '')}",
|
|
119
|
+
f" Mood: {typo.get('Mood/Style Keywords', '')}",
|
|
120
|
+
f" Google Fonts: {typo.get('Google Fonts URL', '')}",
|
|
121
|
+
"",
|
|
122
|
+
f"**Key Effects:** {style.get('Effects & Animation', '')}",
|
|
123
|
+
"</design_system_context>",
|
|
124
|
+
]
|
|
125
|
+
return "\n".join(lines)
|
|
126
|
+
except Exception:
|
|
127
|
+
return ""
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _build_animations_xml(keywords: str, scripts_path: Optional[Path]) -> str:
|
|
131
|
+
"""Build <animation_framework_context> XML from animations.csv if available."""
|
|
132
|
+
try:
|
|
133
|
+
lines = ["<animation_framework_context>"]
|
|
134
|
+
try: # local animations.csv via rebly core
|
|
135
|
+
from core import search as local_search, CSV_CONFIG as local_cfg
|
|
136
|
+
if "animations" in local_cfg:
|
|
137
|
+
anim_r = local_search(keywords, domain="animations", max_results=5)
|
|
138
|
+
patterns = anim_r.get("results", [])
|
|
139
|
+
if patterns:
|
|
140
|
+
lines.append(" <animation_patterns>")
|
|
141
|
+
for p in patterns:
|
|
142
|
+
lines.append(f" <pattern name=\"{p.get('name', '')}\"")
|
|
143
|
+
lines.append(f" css=\"{p.get('css_keyframes', '')}\"")
|
|
144
|
+
lines.append(f" easing=\"{p.get('easing', '')}\"")
|
|
145
|
+
lines.append(f" duration=\"{p.get('duration', '')}\"/>")
|
|
146
|
+
lines.append(" </animation_patterns>")
|
|
147
|
+
except Exception:
|
|
148
|
+
pass
|
|
149
|
+
|
|
150
|
+
lines.append(_ANIMATION_GUIDELINES)
|
|
151
|
+
lines.append("</animation_framework_context>")
|
|
152
|
+
return "\n".join(lines)
|
|
153
|
+
except Exception:
|
|
154
|
+
return ""
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _build_ux_guidelines_xml(keywords: str, scripts_path: Path) -> str:
|
|
158
|
+
"""Build <ux_guidelines_context> XML from ux-guidelines.csv."""
|
|
159
|
+
try:
|
|
160
|
+
ux_mod = _load_module(scripts_path / "core.py", "ux_core")
|
|
161
|
+
if not ux_mod or not hasattr(ux_mod, "search"):
|
|
162
|
+
return ""
|
|
163
|
+
|
|
164
|
+
result = ux_mod.search(keywords, domain="ux", max_results=3)
|
|
165
|
+
guidelines = result.get("results", [])
|
|
166
|
+
if not guidelines:
|
|
167
|
+
return ""
|
|
168
|
+
|
|
169
|
+
lines = ["<ux_guidelines_context>"]
|
|
170
|
+
for g in guidelines:
|
|
171
|
+
lines.append(f" <guideline category=\"{g.get('Category', '')}\" issue=\"{g.get('Issue', '')}\">")
|
|
172
|
+
do = g.get("Do", "")
|
|
173
|
+
dont = g.get("Don't", "")
|
|
174
|
+
if do:
|
|
175
|
+
lines.append(f" <do>{do}</do>")
|
|
176
|
+
if dont:
|
|
177
|
+
lines.append(f" <dont>{dont}</dont>")
|
|
178
|
+
lines.append(" </guideline>")
|
|
179
|
+
lines.append("</ux_guidelines_context>")
|
|
180
|
+
return "\n".join(lines)
|
|
181
|
+
except Exception:
|
|
182
|
+
return ""
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def build_ux_context(section_name: str, section_description: str) -> dict:
|
|
186
|
+
"""Query ui-ux-pro-max skill; return dict with design_system, animations, ux_guidelines XML strings."""
|
|
187
|
+
keywords = f"{section_name} {section_description}".strip()
|
|
188
|
+
scripts_path = _find_ux_skill()
|
|
189
|
+
design_system, ux_guidelines = "", ""
|
|
190
|
+
if scripts_path:
|
|
191
|
+
design_system = _build_design_system_xml(keywords, scripts_path)
|
|
192
|
+
ux_guidelines = _build_ux_guidelines_xml(keywords, scripts_path)
|
|
193
|
+
return {
|
|
194
|
+
"design_system": design_system,
|
|
195
|
+
"animations": _build_animations_xml(keywords, scripts_path),
|
|
196
|
+
"ux_guidelines": ux_guidelines,
|
|
197
|
+
}
|
|
@@ -34,7 +34,11 @@ You are an expert Shopify OS2.0 theme developer. Generate production-ready secti
|
|
|
34
34
|
{{ theme_dna_context }}
|
|
35
35
|
</theme_dna>
|
|
36
36
|
|
|
37
|
-
{{
|
|
37
|
+
{{ design_system_context }}
|
|
38
|
+
|
|
39
|
+
{{ animation_framework_context }}
|
|
40
|
+
|
|
41
|
+
{{ ux_guidelines_context }}
|
|
38
42
|
|
|
39
43
|
<task>
|
|
40
44
|
<name>{{ name }}</name>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rebly-sections",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Shopify section AI coding skill installer for Claude Code and Antigravity Kit",
|
|
5
5
|
"author": "Rebly Sections",
|
|
6
6
|
"homepage": "https://github.com/rebly-sections/sections-ai#readme",
|