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
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
[![arXiv: 2607.20775](https://img.shields.io/badge/arXiv-2607.20775-b31b1b.svg)](https://arxiv.org/abs/2607.20775)
[![CI](https://github.com/microsoft/flint-chart/actions/workflows/ci.yml/badge.svg)](https://github.com/microsoft/flint-chart/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Discord](https://img.shields.io/badge/discord-chat-green?logo=discord)](https://discord.gg/hnm4Y8YX8)
[![WeChat](https://img.shields.io/badge/wechat-group-07C160?logo=wechat&logoColor=white)](#wechat)

**Please visit:** [**Flint Project Site**](https://microsoft.github.io/flint-chart/) | [**Visual Themes**](https://microsoft.github.io/flint-chart/#/themes) | [**MCP Server Guide**](https://microsoft.github.io/flint-chart/#/mcp) | [**中文主页**](https://microsoft.github.io/flint-chart/#/zh)

Expand Down Expand Up @@ -297,6 +299,19 @@ Flint is built by [Microsoft Research](https://www.microsoft.com/en-us/research/
in collaboration with the [IDEAS Lab](https://ideas-lab.net/), Renmin University
of China. We welcome you to join us — see [Contributing](#contributing) to get involved.

## Community

Chat with the team and other users:

- **Discord**[join the server](https://discord.gg/hnm4Y8YX8)
- **WeChat** — scan the QR code to join the user group

<a id="wechat"></a>

<p align="center">
<img src="docs/figs/QR-code.png" alt="Flint WeChat user group QR code" width="240">
</p>

A research paper describing Flint is coming soon.

## Trademarks
Expand All @@ -311,3 +326,4 @@ or logos is subject to those third parties' policies.
## License

[MIT](LICENSE) © Microsoft Corporation

Binary file added docs/figs/QR-code.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 0 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

102 changes: 99 additions & 3 deletions site/src/components/SiteShell.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { CSSProperties, KeyboardEvent, ReactNode } from 'react';
import type { CSSProperties, KeyboardEvent, MouseEvent, ReactNode } from 'react';
import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useLocation } from 'react-router-dom';
import { useLocation, useNavigate } from 'react-router-dom';
import { LocaleLink } from '../i18n/LocaleLink';
import { useLocale } from '../i18n/LocaleContext';
import { stripLocale } from '../i18n/paths';
import type { Locale } from '../i18n/locales';
import { CONTENT_MAX_WIDTH, GITHUB_REPO, siteTheme } from '../shared/theme';
import { CONTENT_MAX_WIDTH, DISCORD_INVITE, GITHUB_REPO, LANDING_SCROLL_TO_KEY, WECHAT_SECTION_ID, siteTheme } from '../shared/theme';
import { scrollToHeading } from '../shared/scroll-to-heading';

const GITHUB_REPO_API = 'https://api.github.com/repos/microsoft/flint-chart';
const GITHUB_STARS_CACHE_KEY = 'flint-chart.github-stars';
Expand Down Expand Up @@ -84,6 +85,10 @@ export function SiteNavBar(_props: { flush?: boolean } = {}) {

<div className="site-nav-actions" style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<LanguageSwitch />
<div style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
<WeChatLink />
<DiscordLink />
</div>
<GitHubLink />
</div>
</header>
Expand Down Expand Up @@ -327,6 +332,69 @@ function LanguageSwitch() {
);
}

function WeChatLink() {
const { t } = useTranslation();
const { pathname } = useLocation();
const navigate = useNavigate();
const { lp } = useLocale();
const [hovered, setHovered] = useState(false);
const logical = stripLocale(pathname);

const onClick = (event: MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
if (logical === '/') {
scrollToHeading(WECHAT_SECTION_ID);
return;
}
try {
sessionStorage.setItem(LANDING_SCROLL_TO_KEY, WECHAT_SECTION_ID);
} catch {
// Privacy modes may block storage.
}
navigate(lp('/'));
};

return (
<a
href={lp(`/#${WECHAT_SECTION_ID}`)}
onClick={onClick}
aria-label={t('nav.wechatAria')}
title={t('nav.wechatTitle')}
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
style={{
...socialIconLinkStyle,
color: hovered ? siteTheme.accent : siteTheme.text,
}}
>
<WeChatIcon />
</a>
);
}

function DiscordLink() {
const { t } = useTranslation();
const [hovered, setHovered] = useState(false);

return (
<a
href={DISCORD_INVITE}
target="_blank"
rel="noreferrer"
aria-label={t('nav.discordAria')}
title={t('nav.discordTitle')}
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
style={{
...socialIconLinkStyle,
color: hovered ? siteTheme.accent : siteTheme.text,
}}
>
<DiscordIcon />
</a>
);
}

function GitHubLink() {
const { t, i18n } = useTranslation();
const [hovered, setHovered] = useState(false);
Expand Down Expand Up @@ -468,6 +536,22 @@ export function GitHubIcon({ size = 15 }: { size?: number } = {}) {
);
}

export function DiscordIcon({ size = 16 }: { size?: number } = {}) {
return (
<svg viewBox="0 0 24 24" width={size} height={size} fill="currentColor" aria-hidden="true">
<path d="M20.317 4.37a19.79 19.79 0 0 0-4.885-1.515.07.07 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z" />
</svg>
);
}

export function WeChatIcon({ size = 16 }: { size?: number } = {}) {
return (
<svg viewBox="0 0 24 24" width={size} height={size} fill="currentColor" aria-hidden="true">
<path d="M8.691 2.188C3.891 2.188 0 5.476 0 9.53c0 2.212 1.17 4.203 3.002 5.55a.59.59 0 0 1 .213.665l-.39 1.48c-.019.07-.048.141-.048.213 0 .163.13.295.29.295a.326.326 0 0 0 .131-.035l1.877-.858a.773.773 0 0 1 .446-.068 9.81 9.81 0 0 0 3.17.508c.447 0 .883-.033 1.309-.094-.21-.582-.327-1.2-.327-1.847 0-3.516 3.287-6.366 7.34-6.366.196 0 .39.007.582.02C17.53 4.63 13.51 2.188 8.691 2.188zm-2.548 4.4c.54 0 .978.45.978.998s-.438.998-.978.998c-.54 0-.978-.45-.978-.998s.439-.998.978-.998zm5.096 0c.54 0 .978.45.978.998s-.438.998-.978.998c-.54 0-.978-.45-.978-.998s.439-.998.978-.998zM24 13.47c0-3.176-3.162-5.75-7.06-5.75-3.899 0-7.06 2.574-7.06 5.75s3.161 5.75 7.06 5.75c.696 0 1.367-.086 2-.244a.59.59 0 0 1 .378.058l1.403.642a.25.25 0 0 0 .105.023c.127 0 .23-.103.23-.23 0-.056-.021-.11-.06-.152l-.292-1.106a.49.49 0 0 1 .177-.55C22.916 16.72 24 15.205 24 13.47zm-9.388-1.248c-.427 0-.773.356-.773.795 0 .44.346.795.773.795.427 0 .773-.356.773-.795 0-.439-.346-.795-.773-.795zm4.656 0c-.427 0-.773.356-.773.795 0 .44.346.795.773.795.427 0 .773-.356.773-.795 0-.439-.346-.795-.773-.795z" />
</svg>
);
}

export function LabIcon({ size = 17 }: { size?: number } = {}) {
return (
<svg viewBox="0 0 24 24" width={size} height={size} fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
Expand All @@ -491,6 +575,18 @@ const navLinkStyle: CSSProperties = {
letterSpacing: '0.01em',
};

const socialIconLinkStyle: CSSProperties = {
...navLinkStyle,
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
width: 28,
height: 28,
borderRadius: 6,
textDecoration: 'none',
transition: 'color 120ms ease, background 120ms ease',
};

/**
* Required Microsoft site disclosures.
*
Expand Down
7 changes: 7 additions & 0 deletions site/src/i18n/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
"githubAriaStars": "GitHub repository, {{count}} stars",
"githubTitle": "View on GitHub",
"githubTitleStars": "View on GitHub ({{count}} stars)",
"wechatAria": "WeChat community",
"wechatTitle": "Join the WeChat group",
"discordAria": "Discord community",
"discordTitle": "Join Discord",
"langEn": "EN",
"langZh": "中文",
"langSwitchAria": "Switch language"
Expand Down Expand Up @@ -405,6 +409,9 @@
"closingBody": "Open source and ready to use. Start from GitHub or browse examples in the gallery.",
"viewGithub": "View on GitHub",
"closingCollab": "Flint is built by <msr>Microsoft Research</msr> in collaboration with the <ideas>IDEAS Lab</ideas>, Renmin University of China.",
"wechatTitle": "Join the Flint WeChat group",
"wechatBody": "Scan the QR code to join the Flint user WeChat group and chat with other users.",
"wechatAlt": "QR code for the Flint WeChat user group",
"features": {
"semantic": {
"title": "Specify with semantic types",
Expand Down
7 changes: 7 additions & 0 deletions site/src/i18n/messages/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
"githubAriaStars": "GitHub 仓库,{{count}} 星",
"githubTitle": "在 GitHub 上查看",
"githubTitleStars": "在 GitHub 上查看({{count}} 星)",
"wechatAria": "微信社群",
"wechatTitle": "加入微信群",
"discordAria": "Discord 社群",
"discordTitle": "加入 Discord",
"langEn": "EN",
"langZh": "中文",
"langSwitchAria": "切换语言"
Expand Down Expand Up @@ -405,6 +409,9 @@
"closingBody": "Flint 已开源,可直接使用。前往 GitHub 获取源码,或先浏览图表示例。",
"viewGithub": "在 GitHub 上查看",
"closingCollab": "Flint 由 <msr>Microsoft Research</msr> 与中国人民大学 <ideas>IDEAS Lab</ideas> 合作构建。",
"wechatTitle": "加入 Flint 用户微信群",
"wechatBody": "扫码加入 Flint 用户微信群,与其他用户交流。",
"wechatAlt": "Flint 用户微信群二维码",
"features": {
"semantic": {
"title": "用语义类型表达数据含义",
Expand Down
40 changes: 38 additions & 2 deletions site/src/routes/Landing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ import {
getSupportedBackends,
type PreviewBackend,
} from '../shared/supported-backends';
import { GITHUB_REPO, siteTheme } from '../shared/theme';
import { GITHUB_REPO, LANDING_SCROLL_TO_KEY, WECHAT_SECTION_ID, siteTheme } from '../shared/theme';
import { scrollToHeading } from '../shared/scroll-to-heading';
import flintLogo from '../assets/flint-logo.svg';
import wechatQr from '../../../docs/figs/QR-code.png';

/**
* Front page: flat "paper" look inspired by Microsoft data-formulator. A
Expand All @@ -31,6 +33,21 @@ export function Landing() {
const { t } = useTranslation();
const features = useMemo(() => getFeatures(t), [t]);

useEffect(() => {
let pending: string | null = null;
try {
pending = sessionStorage.getItem(LANDING_SCROLL_TO_KEY);
if (pending) sessionStorage.removeItem(LANDING_SCROLL_TO_KEY);
} catch {
// Privacy modes may block storage.
}
if (pending !== WECHAT_SECTION_ID) return;
const timer = window.setTimeout(() => {
scrollToHeading(WECHAT_SECTION_ID);
}, 50);
return () => window.clearTimeout(timer);
}, []);

return (
<div style={pageStyle}>
<style>{landingInteractiveStyles}</style>
Expand Down Expand Up @@ -290,7 +307,7 @@ export function Landing() {
</section>

{/* ---- Closing CTA -------------------------------------------- */}
<section style={{ ...sectionStyle, paddingTop: 56, paddingBottom: 88, textAlign: 'center' }}>
<section style={{ ...sectionStyle, paddingTop: 56, paddingBottom: 32, textAlign: 'center' }}>
<h2 style={{ fontSize: 26, margin: '0 0 14px', fontWeight: 500 }}>
{t('landing.closingTitle')}
</h2>
Expand Down Expand Up @@ -331,6 +348,25 @@ export function Landing() {
/>
</p>
</section>

{/* ---- WeChat community -------------------------------------- */}
<section
id={WECHAT_SECTION_ID}
style={{ ...sectionStyle, paddingTop: 20, paddingBottom: 72, textAlign: 'center' }}
>
<h2 style={{ fontSize: 22, margin: '0 0 10px', fontWeight: 500 }}>
{t('landing.wechatTitle')}
</h2>
<p style={{ margin: '0 0 24px', color: siteTheme.text, fontSize: 15, lineHeight: 1.6 }}>
{t('landing.wechatBody')}
</p>
<img
src={wechatQr}
alt={t('landing.wechatAlt')}
width={220}
style={{ display: 'block', margin: '0 auto', maxWidth: '100%', height: 'auto' }}
/>
</section>
</main>
<MicrosoftDisclosures />
</div>
Expand Down
9 changes: 9 additions & 0 deletions site/src/shared/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,12 @@ export const siteTheme = {
export const CONTENT_MAX_WIDTH = 1180;

export const GITHUB_REPO = 'https://github.com/microsoft/flint-chart';

/** Community Discord invite. */
export const DISCORD_INVITE = 'https://discord.gg/hnm4Y8YX8';

/** Landing-page section id for the WeChat QR block. */
export const WECHAT_SECTION_ID = 'wechat';

/** sessionStorage key used to scroll to a landing section after navigating home. */
export const LANDING_SCROLL_TO_KEY = 'flint-landing-scroll-to';
Loading