Skip to content

Commit f71ef65

Browse files
authored
Merge pull request #64 from nguyenhy/deploy/0.0.3
Deploy/0.0.3
2 parents 3faf885 + e39693d commit f71ef65

File tree

40 files changed

+770
-782
lines changed

40 files changed

+770
-782
lines changed

PROMPT_THUMB.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
You are a thumbnail designer creating consistent, brand-aligned thumbnails for technical blog posts.
2+
3+
# Your task
4+
read the content of a blog post and output a final DALL·E-style prompt to generate the thumbnail.
5+
6+
# Steps
7+
8+
1. Read the provided blog text.
9+
2. Detect the main topic (e.g. JavaScript, HTML, CSS, API, Security, Container, etc.).
10+
3. Identify the specific theme or focus of the post — what this article is really about (e.g. "avoiding burnout as a developer", "how React handles rendering", "Docker image optimization").
11+
4. Extract 3–5 visual metaphors or symbolic elements that capture the specific message.
12+
5. Look up the accent color and mood using the below map:
13+
"javascript": { "color": "#FACC15", "mood": "energetic, creative" },
14+
"css": { "color": "#3B82F6", "mood": "clean, elegant, creative" },
15+
"html": { "color": "#F97316", "mood": "bold, foundational" },
16+
"security": { "color": "#2563EB", "mood": "trustworthy, vigilant" },
17+
"api": { "color": "#0EA5E9", "mood": "connected, logical" },
18+
"backend": { "color": "#64748B", "mood": "stable, serious" },
19+
"infra": { "color": "#64748B", "mood": "stable, dependable" },
20+
"container": { "color": "#1D4ED8", "mood": "structured, technical" },
21+
"system": { "color": "#F59E0B", "mood": "balanced, thoughtful" },
22+
"meta": { "color": "#8B5CF6", "mood": "modern, experimental" }
23+
6. create variable that later fill the final prompt
24+
- topic: [topic]
25+
- subject: [specific idea or focus of post]
26+
- accent_color: [hex]
27+
- mood: [keyword]
28+
- keywords: [comma-separated]
29+
30+
31+
# Output Format
32+
```
33+
- You are professional cartoon artist and decide to create blog thumbnail illustration for a post about {subject} in the context of {topic}
34+
- Always follow rules:
35+
- No text, no title, no logo.
36+
- Consistent with other thumbnails in the same flat, minimal style.
37+
- Aspect ratio 16:9.
38+
- Focus visually on {keywords} as the central, dominant elements of the composition, not background details.
39+
- The main subject should be instantly recognizable and fill most of the frame, clearly conveying the concept even without any text.
40+
- If using reallife, implement work flow, make sure the order and the components is correct
41+
- If using code, make sure it correct syntax, valid context and result
42+
- Do not include:
43+
- Any real-world, copyrighted, or licensed characters.
44+
- Any cartoon, mascot, or character that resembles known intellectual property
45+
- Any human or humanoid figures
46+
- Keep the image abstract, conceptual, and professional, using clear forms and visual metaphors to express the idea.
47+
- Mood: {mood}.
48+
- Colors and Style:
49+
- Base color: white
50+
- Accent color: {accent_color}
51+
- clean
52+
- minimal composition with flat illustration style
53+
- soft gradients
54+
- modern
55+
- geometric or abstract background
56+
```

package-lock.json

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

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "hyn",
33
"description": "Personal blog to explore fresh insights and elevate your tech skills daily with innovative articles and guidance",
44
"type": "module",
5-
"version": "0.0.2",
5+
"version": "0.0.3",
66
"scripts": {
77
"dev": "astro dev --force",
88
"build": "astro build --force",

src/components/UITabs.astro

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
---
2+
import { randStr } from "./utils/id";
3+
import type { Tab } from "./UITabs.types";
4+
5+
interface Props {
6+
tabs: Tab[];
7+
activeId?: string;
8+
}
9+
10+
const cid = randStr();
11+
const { tabs, activeId: rawActivateId, ...others } = Astro.props;
12+
const activeId = rawActivateId || (tabs.length ? tabs[0].id : "");
13+
const props: Props = { tabs, activeId };
14+
---
15+
16+
<astro-uitabs class="o--ui_tabs" data-cid={cid}>
17+
<div class="tabs" role="tablist" aria-label="Content Tabs" {...others}>
18+
{
19+
tabs.map((tab) => (
20+
<button
21+
type="button"
22+
role="tab"
23+
id={`uitabs_${cid}-tab-${tab.id}`}
24+
aria-controls={`uitabs_${cid}-panel-${tab.id}`}
25+
aria-selected={tab.id === activeId}
26+
tabindex="0"
27+
class:list={[
28+
"px-4 py-2 border-b-2 transition",
29+
tab.id === activeId
30+
? "border-blue-600 text-blue-600 font-semibold"
31+
: "border-transparent text-gray-600 hover:text-blue-600",
32+
]}
33+
>
34+
{tab.label}
35+
</button>
36+
))
37+
}
38+
</div>
39+
40+
{
41+
tabs.map((tab) => (
42+
<div
43+
id={`uitabs_${cid}-panel-${tab.id}`}
44+
role="tabpanel"
45+
tabindex="0"
46+
aria-labelledby={`uitabs_${cid}-tab-${tab.id}`}
47+
hidden={tab.id !== activeId}
48+
class="py-4"
49+
>
50+
<tab.content.tag {...tab.content.attrs} />
51+
</div>
52+
))
53+
}
54+
</astro-uitabs>
55+
56+
<script is:inline define:vars={{ cid, props }} data-cid={cid}>
57+
window.$astroProps = window.$astroProps || {};
58+
window.$astroProps[cid] = props;
59+
60+
const $script = document.querySelector(`script[data-cid="${cid}"]`);
61+
if ($script) {
62+
$script.remove();
63+
}
64+
</script>
65+
66+
<script></script>
67+
68+
<script>
69+
class AstroPlayground extends HTMLElement {
70+
connectedCallback() {
71+
const tablist =
72+
this.querySelector<HTMLDivElement>('[role="tablist"]')!;
73+
const tabs =
74+
tablist.querySelectorAll<HTMLButtonElement>('[role="tab"]');
75+
const tabpanels =
76+
tablist.querySelectorAll<HTMLDivElement>('[role="tabpanel"]');
77+
78+
tabs.forEach((tab) => {
79+
tab.addEventListener("click", () =>
80+
this.activateTab(tabs, tab),
81+
);
82+
});
83+
}
84+
85+
activateTab(
86+
tabs: NodeListOf<HTMLButtonElement>,
87+
tab: HTMLButtonElement,
88+
) {
89+
tabs.forEach((item) => {
90+
const isActive = item === tab;
91+
const ariaControls = item.getAttribute("aria-controls");
92+
93+
item.setAttribute("aria-selected", isActive.toString());
94+
const panel = ariaControls
95+
? document.getElementById(ariaControls)
96+
: null;
97+
if (panel) {
98+
panel.hidden = !isActive;
99+
}
100+
});
101+
}
102+
}
103+
customElements.define("astro-uitabs", AstroPlayground);
104+
</script>
105+
106+
<style>
107+
[role="tablist"] {
108+
display: flex;
109+
justify-content: center;
110+
flex-direction: row;
111+
border-bottom: 1px solid black;
112+
padding: 4px;
113+
}
114+
[role="tab"] {
115+
padding: 4px;
116+
min-width: 60px;
117+
118+
background-color: lightgrey;
119+
color: black;
120+
&[aria-selected="true"] {
121+
background-color: grey;
122+
color: white;
123+
}
124+
125+
border: 1px solid black;
126+
&:first-child {
127+
border-radius: 4px 0 0 4px;
128+
border-right: none;
129+
}
130+
&:last-child {
131+
border-radius: 0 4px 4px 0;
132+
border-left: none;
133+
}
134+
}
135+
136+
[role="tabpanel"] {
137+
outline: none;
138+
}
139+
</style>

src/components/UITabs.types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export interface Tab {
2+
id: string;
3+
label: string;
4+
content: {
5+
tag: any;
6+
attrs?: Record<string, any>;
7+
};
8+
contextx?: any;
9+
attrs?: Record<string, any>;
10+
}

0 commit comments

Comments
 (0)