/
spirzen
/
it-knowledge-base
Обзор
Документация
Войти
/
spirzen
/
it-knowledge-base
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
Mobile
src/components/LanguageIntroPlay.jsx
186 строк
6 KB
Spirzen
Big design pack
04 июн 2026, 02:45
04 июн 2026, 02:45
50bc995
Код
Авторство
О чём код?
import React, {useMemo, useState} from 'react'; import BrowserOnly from '@docusaurus/BrowserOnly'; import clsx from 'clsx'; import DemoShell, {DemoCard} from './shared/DemoShell'; import {demoLoadingFallback} from './shared/demoFallback'; import { formatLanguageLabel, getLanguageIntro, KIND_LABELS, LANGUAGE_INTROS, OVERVIEW_ARTICLE, } from './shared/languageIntroData'; import TechIcon from './TechIcon'; import styles from './LanguageIntroPlay.module.css'; const TABS = [ {id: 'about', label: 'Суть'}, {id: 'uses', label: 'Где применяют'}, {id: 'eco', label: 'Экосистема'}, ]; const ACCENT_BY_KIND = { programming: '#6366f1', markup: '#e11d48', style: '#7c3aed', query: '#059669', platform: '#0ea5e9', shell: '#d97706', }; export function LanguageIntroPlayInner({topic, embedded = false}) { const intro = useMemo(() => getLanguageIntro(topic), [topic]); const [tab, setTab] = useState('about'); const [relatedTopic, setRelatedTopic] = useState(null); const display = relatedTopic ? getLanguageIntro(relatedTopic) : intro; if (!intro) { const missing = ( <p className={styles.hint}>Обзор для темы "{topic}" пока не добавлен.</p> ); if (embedded) return missing; return ( <DemoShell> <DemoCard title="Знакомство с языком">{missing}</DemoCard> </DemoShell> ); } const accent = ACCENT_BY_KIND[display.kind] ?? '#6366f1'; const body = ( <div className={styles.root} style={{'--accent': accent}}> <div className={styles.header}> <TechIcon techId={display.id} variant="badge" size="sm" accent={accent} className={styles.icon} title={display.name} /> <div className={styles.headText}> <h5 className={styles.title}>{display.name}</h5> <p className={styles.meta}> {display.category} {display.year ? ` · с ${display.year} г.` : ''} {' · '} {KIND_LABELS[display.kind] ?? display.kind} </p> </div> </div> <div className={styles.chips}> <span className={clsx(styles.chip, styles.chipKind)} style={{background: accent}} > {KIND_LABELS[display.kind]} </span> {display.traits.map((t) => ( <span key={t} className={styles.chip}> {t} </span> ))} </div> <div className={styles.tabRow} role="tablist" aria-label="Разделы обзора"> {TABS.map((t) => ( <button key={t.id} type="button" role="tab" aria-selected={tab === t.id} className={clsx( 'it-demo__btn it-demo__btn--sm', tab !== t.id && 'it-demo__btn--secondary', )} onClick={() => setTab(t.id)} > {t.label} </button> ))} {relatedTopic && ( <button type="button" className={clsx('it-demo__btn it-demo__btn--sm', 'it-demo__btn--secondary')} onClick={() => setRelatedTopic(null)} > ← {intro.name} </button> )} </div> <div className={styles.panel} role="tabpanel"> {tab === 'about' && ( <> <p className={styles.summary}>{display.summary}</p> {display.note && <p className={styles.note}>{display.note}</p>} </> )} {tab === 'uses' && ( <ul className={styles.list}> {display.uses.map((u) => ( <li key={u}>{u}</li> ))} </ul> )} {tab === 'eco' && ( <ul className={styles.list}> {display.ecosystem.map((e) => ( <li key={e}>{e}</li> ))} </ul> )} </div> {display.related?.length > 0 && !relatedTopic && ( <div className={styles.related}> <span className={styles.hint}>Рядом в обзоре:</span> {display.related .filter((id) => LANGUAGE_INTROS[id]) .map((id) => ( <button key={id} type="button" className={styles.relatedBtn} onClick={() => { setRelatedTopic(id); setTab('about'); }} > {formatLanguageLabel(LANGUAGE_INTROS[id])} </button> ))} </div> )} <p className={styles.footer}> Полный обзор всех языков — в статье{' '} <a href={OVERVIEW_ARTICLE}>"Основные языки"</a>. </p> </div> ); if (embedded) return body; return ( <DemoShell> <DemoCard title="Краткое знакомство" subtitle="Обзор из раздела "Основные языки" — без углубления в синтаксис" > {body} </DemoCard> </DemoShell> ); } export default function LanguageIntroPlay(props) { return ( <BrowserOnly fallback={demoLoadingFallback('Загрузка обзора языка…')}> {() => <LanguageIntroPlayInner {...props} />} </BrowserOnly> ); }