Skip to content
Merged
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
43 changes: 37 additions & 6 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{font-family:var(--sans);font-size:16px;line-height:1.55;color:var(--ink);background:var(--bg);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;}
html{scroll-behavior:smooth;height:100%}
body{display:flex;flex-direction:column;min-height:100vh;font-family:var(--sans);font-size:16px;line-height:1.55;color:var(--ink);background:var(--bg);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;}
img,svg{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:none;cursor:pointer}
Expand All @@ -69,8 +69,8 @@ h3{font-size:24px;line-height:1.25}
h4{font-size:18px;line-height:1.3}
.lead{font-size:18px;line-height:1.55;color:var(--ink-2);max-width:62ch}

.nav{position:sticky;top:0;z-index:50;background:rgba(254,254,255,.98);backdrop-filter:saturate(180%) blur(14px);-webkit-backdrop-filter:saturate(180%) blur(14px);border-bottom:1px solid var(--line);}
.nav-inner{display:flex;align-items:center;gap:18px;height:64px}
.nav{position:sticky;top:0;z-index:50;background:rgba(254,254,255,.98);backdrop-filter:saturate(180%) blur(14px);-webkit-backdrop-filter:saturate(180%) blur(14px);border-bottom:1px solid var(--line);display:flex;flex-direction:column;overflow:hidden}
.nav-inner{display:flex;align-items:center;gap:18px;height:64px;padding:0 28px;width:100%;max-width:1200px;margin:0 auto}
.nav-logo{display:flex;align-items:center;gap:10px;color:var(--brand)}
.nav-logo:hover{color:var(--brand-on)}
.nav-logo .nav-mark{width:26px;height:auto;display:none}
Expand All @@ -79,6 +79,23 @@ h4{font-size:18px;line-height:1.3}
.nav-links a{font-size:14px;color:var(--ink-2);padding:8px 11px;border-radius:var(--r-sm);transition:background .15s,color .15s;}
.nav-links a:hover{background:var(--surface);color:var(--ink)}
.nav-links a.is-active{background:var(--surface);color:var(--ink);font-weight:500}
.nav-backdrop{position:fixed;inset:0;background:rgba(25,24,23,.3);z-index:99;animation:fadeIn .3s cubic-bezier(.4,0,.2,1)}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
.nav-burger{display:none;flex-direction:column;gap:4px;background:none;border:none;cursor:pointer;padding:8px;z-index:101;order:-1}
.nav-burger span{width:22px;height:2px;background:var(--ink);border-radius:1px;transition:all .3s}
.nav-mobile-menu{position:fixed;top:0;left:0;height:100vh;width:280px;background:var(--bg);flex-direction:column;gap:0;z-index:100;display:flex;transform:translateX(-100%);animation:slideLeft .3s cubic-bezier(.4,0,.2,1) forwards;overflow-y:auto}
.nav-mobile-menu-header{display:flex;align-items:center;justify-content:space-between;padding:16px 28px;border-bottom:1px solid var(--line);height:64px;flex-shrink:0}
.nav-mobile-menu-logo{height:24px;width:auto;color:var(--brand)}
.nav-mobile-menu-close{background:none;border:none;cursor:pointer;padding:4px;color:var(--ink);font-size:28px;display:flex;align-items:center;justify-content:center;line-height:1;transition:color .15s}
.nav-mobile-menu-close:hover{color:var(--ink-2)}
.nav-mobile-menu a{padding:16px 28px;font-size:15px;color:var(--ink-2);transition:background .15s;border:none;display:block}
.nav-mobile-menu a:hover{background:var(--surface);color:var(--ink)}
.nav-mobile-menu a.is-active{background:var(--surface);color:var(--ink);font-weight:500}
.nav-mobile-menu .lang-switcher{width:100%;padding:16px 28px;border-top:1px solid var(--line)}
.nav-mobile-menu .lang-trigger{width:100%;justify-content:space-between;padding:8px 12px}
.lang-list-inline{position:static;width:100%;min-width:0;margin-top:8px;padding:4px;box-shadow:none;border-color:var(--line)}
.lang-list-inline button{padding:10px 10px}
@keyframes slideLeft{from{transform:translateX(-100%)}to{transform:translateX(0)}}
.nav-right{display:flex;align-items:center;gap:10px}
.lang-switcher{position:relative;display:inline-block}
.lang-trigger{display:inline-flex;align-items:center;gap:6px;background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:7px 10px 7px 9px;font-family:var(--mono);font-size:11px;letter-spacing:.05em;color:var(--ink-2);cursor:pointer;transition:background .15s,border-color .15s,color .15s;}
Expand Down Expand Up @@ -317,6 +334,9 @@ h4{font-size:18px;line-height:1.3}
.dot{width:6px;height:6px;border-radius:50%;background:currentColor;display:inline-block}
.contrib-card .footer a{color:var(--brand-on);font-weight:500;display:inline-flex;align-items:center;gap:4px}

.citation-grid{display:grid;grid-template-columns:1.3fr .9fr;gap:32px}
.community-grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:18px;margin-top:32px}
.abt-mission-grid{display:grid;grid-template-columns:1.3fr .9fr;gap:32px;margin-top:32px}
.guides-section{margin-top:64px}
.guides-section .sec-eyebrow{font-family:var(--mono);font-size:12px;color:var(--ink-3);margin-bottom:14px}
.guides-section .sec-eyebrow .num{color:var(--brand);font-weight:500}
Expand Down Expand Up @@ -487,7 +507,7 @@ h4{font-size:18px;line-height:1.3}
.cs-cta{padding-top:24px;border-top:1px dashed var(--line);font-size:14px;color:var(--ink-2);line-height:1.55}
.cs-cta p{max-width:62ch}

.foot{background:var(--ink-bg);color:var(--ink-text-2);padding:72px 0 36px;border-top:none}
.foot{margin-top:auto;background:var(--ink-bg);color:var(--ink-text-2);padding:72px 0 36px;border-top:none}
.foot-grid{display:grid;grid-template-columns:1.4fr 1fr 1fr 1fr;gap:48px}
.foot h5{font-family:var(--mono);font-size:11px;color:var(--ink-text);margin-bottom:14px;letter-spacing:.05em;font-weight:500}
.foot ul{list-style:none}
Expand All @@ -501,6 +521,12 @@ h4{font-size:18px;line-height:1.3}
.nav-logo .nav-lockup{display:none}
.nav-logo .nav-mark{display:block}
.nav-links a{padding:8px 8px;font-size:13px}
.nav-burger{display:flex;margin-left:8px}
.nav-links{display:none}
.nav-mobile-menu{display:flex}
.lang-switcher-desktop{display:none}
.nav-right{margin-left:auto}
.nav-inner{padding-left:0!important}
}
@media(max-width:980px){
h1{font-size:54px}h2{font-size:34px}
Expand All @@ -522,6 +548,7 @@ h4{font-size:18px;line-height:1.3}
.news-grid{grid-template-columns:1fr}.inst-grid{grid-template-columns:repeat(2,1fr)}
.inst-grid{grid-template-columns:repeat(2,1fr)}.team-grid{grid-template-columns:1fr}
.comm-stats{grid-template-columns:1fr 1fr}
.community-grid{grid-template-columns:1fr 1fr}
.student-grid{grid-template-columns:repeat(4,1fr)}
.students-card{padding:22px 20px 16px}
.mock-chrome{padding:10px 14px}.mock-url{font-size:10.5px}
Expand All @@ -531,7 +558,7 @@ h4{font-size:18px;line-height:1.3}
.wm{width:200px}.wm-lg{width:130px}.wm-sm{width:150px}
}
@media(max-width:740px){
.nav-links{display:none}.nav-inner{gap:12px}.nav-right{gap:6px}.lang-trigger{padding:6px 8px}
.nav-burger{display:flex;margin-left:8px}.nav-links{display:none}.nav-mobile-menu{display:flex}.nav-inner{gap:12px;padding-left:0!important}.lang-switcher-desktop{display:none}.lang-trigger{padding:6px 8px}.nav-right{margin-left:auto}
.hero{padding:48px 0 56px}.hero h1{font-size:44px;letter-spacing:-.03em}
.hero-sub{font-size:17px;margin-top:20px}.hero-cta .btn{font-size:13.5px}
.section{padding:64px 0}.section--tight{padding:48px 0}
Expand All @@ -543,6 +570,10 @@ h4{font-size:18px;line-height:1.3}
.showcase-explain{grid-template-columns:1fr;gap:12px}
.guide{padding:20px}.guide-head{gap:14px}.guide-head h3{font-size:18px}
.first-pr{padding:24px;gap:20px}.wrap{padding:0 20px}
.citation-grid{grid-template-columns:1fr;gap:20px}
.community-grid{grid-template-columns:1fr}
.cs-meta{grid-template-columns:1fr}
.abt-mission-grid{grid-template-columns:1fr;gap:20px}
}
@media(max-width:640px){
.hero h1{font-size:38px}h1{font-size:36px}h2{font-size:26px}
Expand Down
3 changes: 1 addition & 2 deletions components/community/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export function Footer() {
</a>
</li>
<li>
<a href="mailto:dashai.nocode@gmail.com">{t('ft.em')}</a>
<a href="mailto:contacto@dash-ai.com">{t('ft.em')}</a>
</li>
<li>
<a href="https://github.com/DashAISoftware/dashAI/issues" target="_blank" rel="noopener noreferrer">
Expand All @@ -104,7 +104,6 @@ export function Footer() {

<div className="foot-bottom">
<div>{t('ft.copy')}</div>
<div>{t('ft.proto')}</div>
</div>
</div>
</footer>
Expand Down
113 changes: 111 additions & 2 deletions components/community/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export function Navbar({ route }: { route: string }) {
const setLang = (l: string) => { i18n.changeLanguage(l); try { localStorage.setItem('dashai-lang', l) } catch {} }

const [isOpen, setIsOpen] = useState(false)
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
const { stats, isLoading: statsLoading } = useStats()
const stars = stats?.github.stars ?? null
const switcherRef = useRef<HTMLDivElement>(null)
Expand All @@ -52,14 +53,31 @@ export function Navbar({ route }: { route: string }) {
return () => document.removeEventListener('click', handleClickOutside)
}, [])

function closeMobileMenu() {
setMobileMenuOpen(false)
}

function handleLangSelect(l: Lang) {
setLang(l)
setIsOpen(false)
}

return (
<>
<header className="nav">
<div className="wrap nav-inner">
<button
className="nav-burger"
type="button"
aria-label="Menu"
aria-expanded={mobileMenuOpen}
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
>
<span />
<span />
<span />
</button>

<a href="#home" className="nav-logo" aria-label="dashAI">
<svg className="nav-mark" viewBox="0 0 218.96 237.04">
<use href="#dashai-mark" />
Expand All @@ -82,8 +100,8 @@ export function Navbar({ route }: { route: string }) {
))}
</nav>

<div className="nav-right">
<div className="lang-switcher" ref={switcherRef}>
<div className="nav-right nav-right-desktop">
<div className="lang-switcher lang-switcher-desktop" ref={switcherRef}>
<button
className="lang-trigger"
type="button"
Expand Down Expand Up @@ -170,5 +188,96 @@ export function Navbar({ route }: { route: string }) {
</div>
</div>
</header>

{mobileMenuOpen && (
<>
<div className="nav-backdrop" onClick={closeMobileMenu} />
<nav className="nav-mobile-menu">
<div className="nav-mobile-menu-header">
<svg className="nav-mobile-menu-logo" viewBox="0 0 854 237.04">
<use href="#dashai-lockup" />
</svg>
<button
className="nav-mobile-menu-close"
type="button"
aria-label="Close"
onClick={closeMobileMenu}
>
×
</button>
</div>

{NAV_LINKS.map(({ key, i18nKey }) => (
<a
key={key}
href={`#${key}`}
className={route === key ? 'is-active' : undefined}
onClick={closeMobileMenu}
>
{t(i18nKey)}
</a>
))}

<div className="lang-switcher" ref={switcherRef} style={{ width: '100%' }}>
<button
className="lang-trigger"
type="button"
aria-haspopup="listbox"
aria-expanded={isOpen}
onClick={() => setIsOpen((prev) => !prev)}
>
<svg
className="lang-icon"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth={1.8}
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
>
<circle cx="12" cy="12" r="9" />
<path d="M3 12h18" />
<path d="M12 3a13 13 0 0 1 0 18M12 3a13 13 0 0 0 0 18" />
</svg>
<span className="lang-current">{lang.toUpperCase()}</span>
<svg
className="lang-caret"
viewBox="0 0 12 12"
aria-hidden="true"
>
<path
d="M2 4l4 4 4-4"
fill="none"
stroke="currentColor"
strokeWidth={1.8}
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</button>

{isOpen && (
<ul className="lang-list lang-list-inline" role="listbox">
{LANG_OPTIONS.map(({ code, label }) => (
<li key={code}>
<button
type="button"
role="option"
className={lang === code ? 'is-on' : undefined}
onClick={() => handleLangSelect(code)}
>
<span className="lang-code">{code.toUpperCase()}</span>
<span className="lang-name">{label}</span>
</button>
</li>
))}
</ul>
)}
</div>
</nav>
</>
)}
</>
)
}
4 changes: 2 additions & 2 deletions components/community/routes/AboutRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function AboutRoute() {
<h2 style={{ margin: '16px 0' }}>{t('abt.h')}</h2>
<p className="lead">{t('abt.lead')}</p>

<div style={{ display: 'grid', gridTemplateColumns: '1.3fr .9fr', gap: '32px', marginTop: '32px' }}>
<div className="abt-mission-grid">
<div style={{
background: 'var(--surface)',
border: '1px solid var(--line)',
Expand Down Expand Up @@ -106,7 +106,7 @@ export function AboutRoute() {
<h4 style={{ fontSize: '16px', color: 'var(--ink-text)', marginBottom: '8px' }}>{t('abt.hist.cta.h')}</h4>
<p style={{ fontSize: '14px', color: 'var(--ink-text-2)', lineHeight: '1.55' }}>{t('abt.hist.cta.p')}</p>
</div>
<a className="btn btn--blue" href="mailto:dashai.nocode@gmail.com">
<a className="btn btn--blue" href="mailto:contacto@dash-ai.com">
<span>{t('abt.hist.cta.b')}</span> →
</a>
</div>
Expand Down
12 changes: 5 additions & 7 deletions components/community/routes/CommunityRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@ export function CommunityRoute() {
<h2 style={{ margin: '16px 0' }}>{t('com.h')}</h2>
<p className="lead">{t('com.lead')}</p>

<div style={{
display: 'grid',
gridTemplateColumns: '1fr 1fr 1fr',
gap: '18px',
marginTop: '32px',
}}>
<div className="community-grid">
<div style={{
background: 'var(--bg)',
border: '1px solid var(--line)',
Expand Down Expand Up @@ -60,7 +55,10 @@ export function CommunityRoute() {
<div className="mono" style={{ display: 'inline-block', fontSize: '11px', color: 'var(--ink-3)' }}>EMAIL</div>
<h3 style={{ margin: '14px 0 10px', color: 'var(--ink)' }}>{t('com.e.h')}</h3>
<p style={{ fontSize: '14px', color: 'var(--ink-2)', lineHeight: '1.5' }}>{t('com.e.p')}</p>
<a className="btn btn--sm" style={{ marginTop: '18px' }} href="mailto:dashai.nocode@gmail.com">
<a className="mono" style={{ display: 'block', marginTop: '14px', fontSize: '13px', color: 'var(--brand-on)' }} href="mailto:contacto@dash-ai.com">
contacto@dash-ai.com
</a>
<a className="btn btn--sm" style={{ marginTop: '14px' }} href="mailto:contacto@dash-ai.com">
<span>{t('com.e.cta')}</span> →
</a>
</div>
Expand Down
6 changes: 3 additions & 3 deletions components/community/routes/ContributeRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ export function ContributeRoute() {
<a href="https://discord.gg/CQVqMBjeWP" target="_blank" rel="noopener">
<span>{t('g.lnk.discord')}</span> →
</a>
<a href="mailto:dashai.nocode@gmail.com">
<a href="mailto:contacto@dash-ai.com">
<span>{t('g.lnk.email')}</span> →
</a>
</div>
Expand Down Expand Up @@ -625,7 +625,7 @@ export function ContributeRoute() {
</div>
</div>

<div style={{ display: 'grid', gridTemplateColumns: '1.3fr .9fr', gap: 32 }}>
<div className="citation-grid">
<pre className="code">{`@software{dashai_2026,
title = {dashAI: a Full Open, Full Extensible
Visual ML platform},
Expand All @@ -637,7 +637,7 @@ export function ContributeRoute() {
organization = {dashAI Community},
}`}</pre>

<div style={{ background: 'var(--surface)', border: '1px solid var(--line)', borderRadius: 'var(--r-lg)', padding: 24 }}>
<div className="coc-card" style={{ background: 'var(--surface)', border: '1px solid var(--line)', borderRadius: 'var(--r-lg)', padding: 24 }}>
<h4 style={{ fontSize: 16, marginBottom: 10 }}>{t('cont.coc.h')}</h4>
<p style={{ fontSize: 14, color: 'var(--ink-2)', lineHeight: 1.5 }} dangerouslySetInnerHTML={th('cont.coc.p')} />
<a
Expand Down
2 changes: 1 addition & 1 deletion public/locales/de/community.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"com.d.p": "Live-Support, Release-Ankündigungen und Threads pro Modul (Datasets, Models, Generative, Plugins), um deine Experimente zu teilen.",
"com.e.cta": "Schreiben",
"com.e.h": "Kooperationen.",
"com.e.p": "Fragen, Kooperationen, institutionelle Integrationen oder einfach um zu teilen, was du gerade baust. Antwort in &lt; 48h.",
"com.e.p": "Fragen, Kooperationen, institutionelle Integrationen oder einfach um zu teilen, was du gerade baust. Antwort in < 48h.",
"com.h": "dashAI-Community.",
"com.lead": "Discord für Live-Support, Mailingliste für die monatliche Zusammenfassung, E-Mail für institutionelle Kooperationen.",
"com.n.cta": "Abonnieren",
Expand Down
2 changes: 1 addition & 1 deletion public/locales/de/contribute.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"cont.cit.h": "Zitiere dashAI in deinem Paper.",
"cont.cit.lead": "Wenn dashAI Teil deiner Forschung war, hilft uns eine Zitation, Fördermittel zu sichern und den Katalog weiter auszubauen. BibTeX und Verhaltenskodex unten.",
"cont.coc.h": "Verhaltenskodex",
"cont.coc.p": "dashAI folgt dem Contributor Covenant v2.1. Respekt, Namensnennung und ehrliche technische Diskussion: Das ist alles, was wir erwarten. Vertrauliche Meldungen an <a href=\"mailto:dashai.nocode@gmail.com\" style=\"color:var(--brand-on);font-weight:500\">dashai.nocode@gmail.com</a>.",
"cont.coc.p": "dashAI folgt dem Contributor Covenant v2.1. Respekt, Namensnennung und ehrliche technische Diskussion: Das ist alles, was wir erwarten. Vertrauliche Meldungen an <a href=\"mailto:contacto@dash-ai.com\" style=\"color:var(--brand-on);font-weight:500\">contacto@dash-ai.com</a>.",
"cont.ey": "acht Wege, dich zu beteiligen",
"cont.guide": "Anleitung ansehen",
"cont.h": "Wie du zu dashAI <em>beitragen</em> kannst.",
Expand Down
1 change: 0 additions & 1 deletion public/locales/de/footer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,5 @@
"ft.em": "E-Mail",
"ft.ml": "Mailingliste",
"ft.models": "Modellkatalog",
"ft.proto": "Prototype v3 | Community Hub, Mai 2026",
"ft.rn": "Release Notes"
}
2 changes: 1 addition & 1 deletion public/locales/en/contribute.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"cont.cit.h": "Cite dashAI in your paper.",
"cont.cit.lead": "If dashAI was part of your research, citing it helps us sustain funding and keep growing the catalog. BibTeX and code of conduct below.",
"cont.coc.h": "Code of conduct",
"cont.coc.p": "dashAI follows the Contributor Covenant v2.1. Respect, attribution, and honest technical discussion: that's all we expect. Confidential reports to <a href=\"mailto:dashai.nocode@gmail.com\" style=\"color:var(--brand-on);font-weight:500\">dashai.nocode@gmail.com</a>.",
"cont.coc.p": "dashAI follows the Contributor Covenant v2.1. Respect, attribution, and honest technical discussion: that's all we expect. Confidential reports to <a href=\"mailto:contacto@dash-ai.com\" style=\"color:var(--brand-on);font-weight:500\">contacto@dash-ai.com</a>.",
"cont.ey": "eight ways to join",
"cont.guide": "See guide",
"cont.h": "How to <em>contribute</em> to dashAI.",
Expand Down
1 change: 0 additions & 1 deletion public/locales/en/footer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,5 @@
"ft.em": "Email",
"ft.ml": "Mailing list",
"ft.models": "Models catalog",
"ft.proto": "Prototype v5 | Community Hub, May 2026",
"ft.rn": "Release notes"
}
Loading
Loading