├── .eslintrc.json ├── .gitignore ├── README.md ├── package.json ├── public └── index.html ├── src ├── App.tsx ├── components │ ├── BannerSection.tsx │ ├── CellSection.tsx │ ├── FormSection │ │ ├── FormSection.module.css │ │ └── FormSection.tsx │ ├── ModalSection │ │ ├── ModalSection.module.css │ │ └── ModalSection.tsx │ ├── TimelineSection │ │ ├── TimelineSection.module.css │ │ └── TimelineSection.tsx │ └── TooltipSection │ │ ├── TooltipSection.module.css │ │ └── TooltipSection.tsx ├── helpers │ └── setBackgroundAsSecondary.ts ├── index.css ├── index.tsx └── react-app-env.d.ts ├── tsconfig.json └── yarn.lock /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "react-app", 4 | "react-app/jest" 5 | ], 6 | "parserOptions": { 7 | "project": "./tsconfig.json", 8 | "ecmaVersion": 6, 9 | "sourceType": "module", 10 | "ecmaFeatures": { 11 | "jsx": true, 12 | "restParams": true, 13 | "spread": true 14 | } 15 | }, 16 | "env": { 17 | "browser": true, 18 | "node": true 19 | }, 20 | "globals": { 21 | "Promise": true, 22 | "Set": true, 23 | "Map": true 24 | }, 25 | "rules": { 26 | "react/display-name": "off", 27 | "react/react-in-jsx-scope": "off", 28 | "@typescript-eslint/no-magic-numbers": "off", 29 | "@typescript-eslint/explicit-member-accessibility": "off", 30 | "@typescript-eslint/no-extra-parens": ["error", "all", { 31 | "ignoreJSX": "all" 32 | }], 33 | "@typescript-eslint/no-unused-vars": ["error", { 34 | "ignoreRestSiblings": true 35 | }], 36 | "no-restricted-imports": ["error", { 37 | "patterns": ["@vkontakte/icons/dist/*"] 38 | }], 39 | "no-shadow": "off", 40 | "@typescript-eslint/no-shadow": "warn" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # IDE 4 | .idea 5 | 6 | # dependencies 7 | /node_modules 8 | /.pnp 9 | .pnp.js 10 | 11 | # testing 12 | /coverage 13 | 14 | # production 15 | /build 16 | 17 | # misc 18 | .DS_Store 19 | .env.local 20 | .env.development.local 21 | .env.test.local 22 | .env.production.local 23 | 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with TGUI Example 2 | 3 | ## Available Scripts 4 | 5 | In the project directory, you can run: 6 | 7 | ### `yarn start` 8 | 9 | Runs the app in the development mode.\ 10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 11 | 12 | The page will reload if you make edits.\ 13 | You will also see any lint errors in the console. 14 | 15 | ### `yarn build` 16 | 17 | Builds the app for production to the `build` folder.\ 18 | It correctly bundles React in production mode and optimizes the build for the best performance. 19 | 20 | The build is minified and the filenames include the hashes.\ 21 | Your app is ready to be deployed! 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tgui-example", 3 | "version": "1.0.0", 4 | "private": true, 5 | "homepage": "./", 6 | "devDependencies": { 7 | "@types/jest": "^27.5.2", 8 | "@types/node": "^16.18.73", 9 | "@types/react": "^18.2.48", 10 | "@types/react-dom": "^18.2.18", 11 | "gh-pages": "^6.1.1", 12 | "react-scripts": "5.0.1", 13 | "typescript": "^4.9.5" 14 | }, 15 | "dependencies": { 16 | "@telegram-apps/telegram-ui": "2.1.6", 17 | "react": "18.2.0", 18 | "react-dom": "18.2.0" 19 | }, 20 | "scripts": { 21 | "start": "react-scripts start", 22 | "build": "react-scripts build", 23 | "predeploy": "npm run build", 24 | "deploy": "gh-pages -d build" 25 | }, 26 | "eslintConfig": { 27 | "extends": [ 28 | "react-app", 29 | "react-app/jest" 30 | ] 31 | }, 32 | "browserslist": { 33 | "production": [ 34 | ">0.2%", 35 | "not dead", 36 | "not op_mini all" 37 | ], 38 | "development": [ 39 | "last 1 chrome version", 40 | "last 1 firefox version", 41 | "last 1 safari version" 42 | ] 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | TGUI Example 8 | <% if (process.env.NODE_ENV === 'production') { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { AppRoot, List } from '@telegram-apps/telegram-ui'; 4 | import { CellSection } from './components/CellSection'; 5 | import { FormSection } from './components/FormSection/FormSection'; 6 | import { BannerSection } from './components/BannerSection'; 7 | import { TimelineSection } from './components/TimelineSection/TimelineSection'; 8 | import { TooltipSection } from './components/TooltipSection/TooltipSection'; 9 | import { ModalSection } from './components/ModalSection/ModalSection'; 10 | 11 | export const App = () => ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ); 23 | -------------------------------------------------------------------------------- /src/components/BannerSection.tsx: -------------------------------------------------------------------------------- 1 | import { Banner, Button, Image, Section } from '@telegram-apps/telegram-ui'; 2 | 3 | const TON_SITE_LINK = 'https://ton.space/'; 4 | 5 | export const BannerSection = () => ( 6 |
7 | } 9 | header="Introducing TON Space" 10 | subheader="Start exploring TON in a new, better way" 11 | > 12 | 20 | 21 |
22 | ); 23 | -------------------------------------------------------------------------------- /src/components/CellSection.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | import { Cell, IconContainer, Section } from '@telegram-apps/telegram-ui'; 3 | 4 | import { Icon28Chat } from '@telegram-apps/telegram-ui/dist/icons/28/chat'; 5 | import { Icon28Devices } from '@telegram-apps/telegram-ui/dist/icons/28/devices'; 6 | import { Icon28Stats } from '@telegram-apps/telegram-ui/dist/icons/28/stats'; 7 | 8 | type CellProps = { 9 | id: number; 10 | icon: ReactNode; 11 | text: string; 12 | } 13 | 14 | const cells: CellProps[] = [ 15 | { 16 | id: 1, 17 | icon: , 18 | text: 'Chat Settings', 19 | }, 20 | { 21 | id: 2, 22 | icon: , 23 | text: 'Data and Storage', 24 | }, 25 | { 26 | id: 3, 27 | icon: , 28 | text: 'Devices', 29 | }, 30 | ]; 31 | 32 | export const CellSection = () => ( 33 |
34 | {cells.map((cell) => ( 35 | {cell.icon}} 38 | > 39 | {cell.text} 40 | 41 | ))} 42 |
43 | ); 44 | -------------------------------------------------------------------------------- /src/components/FormSection/FormSection.module.css: -------------------------------------------------------------------------------- 1 | .sliderIcon { 2 | color: var(--tgui--secondary_hint_color); 3 | } 4 | -------------------------------------------------------------------------------- /src/components/FormSection/FormSection.tsx: -------------------------------------------------------------------------------- 1 | import styles from './FormSection.module.css'; 2 | 3 | import { ColorInput, IconContainer, Input, Section, Slider } from '@telegram-apps/telegram-ui'; 4 | import { Icon24SunLow } from '@telegram-apps/telegram-ui/dist/icons/24/sun_low'; 5 | 6 | export const FormSection = () => ( 7 |
8 | 9 | 10 | 14 | 15 | 16 | )} 17 | after={} 18 | /> 19 |
20 | ); 21 | -------------------------------------------------------------------------------- /src/components/ModalSection/ModalSection.module.css: -------------------------------------------------------------------------------- 1 | .image { 2 | display: block; 3 | width: 144px; 4 | height: 144px; 5 | } 6 | -------------------------------------------------------------------------------- /src/components/ModalSection/ModalSection.tsx: -------------------------------------------------------------------------------- 1 | import styles from './ModalSection.module.css'; 2 | import { Button, Modal, Placeholder, Section } from '@telegram-apps/telegram-ui'; 3 | 4 | const PlaceholderImage = () => ( 5 | Telegram sticker 10 | ); 11 | 12 | const ModalWithTrigger = () => ( 13 | } 15 | trigger={} 16 | > 17 | 21 | 22 | 23 | 24 | ); 25 | 26 | export const ModalSection = () => ( 27 |
28 | } 32 | > 33 | 34 | 35 |
36 | ); 37 | -------------------------------------------------------------------------------- /src/components/TimelineSection/TimelineSection.module.css: -------------------------------------------------------------------------------- 1 | .timeline { 2 | padding: 24px 32px; 3 | } 4 | -------------------------------------------------------------------------------- /src/components/TimelineSection/TimelineSection.tsx: -------------------------------------------------------------------------------- 1 | import styles from './TimelineSection.module.css'; 2 | import { Section, Timeline } from '@telegram-apps/telegram-ui'; 3 | 4 | const TIMELINE_ITEMS = [ 5 | { 6 | header: 'Arrived', 7 | description: 'Yesterday', 8 | }, 9 | { 10 | header: 'Departed', 11 | description: 'Today', 12 | }, 13 | { 14 | header: 'In transit', 15 | description: 'Tomorrow', 16 | }, 17 | { 18 | header: 'Processed to delivery center', 19 | description: 'Next week', 20 | }, 21 | { 22 | header: 'Shipped', 23 | description: 'Someday', 24 | }, 25 | ]; 26 | 27 | export const TimelineSection = () => ( 28 |
29 | 30 | {TIMELINE_ITEMS.map((item, index) => ( 31 | 32 | {item.description} 33 | 34 | ))} 35 | 36 |
37 | ); 38 | -------------------------------------------------------------------------------- /src/components/TooltipSection/TooltipSection.module.css: -------------------------------------------------------------------------------- 1 | .button { 2 | min-width: 64px; 3 | } 4 | -------------------------------------------------------------------------------- /src/components/TooltipSection/TooltipSection.tsx: -------------------------------------------------------------------------------- 1 | import { useRef, useState } from 'react'; 2 | import styles from './TooltipSection.module.css'; 3 | 4 | import { Banner, Button, Section, Tooltip } from '@telegram-apps/telegram-ui'; 5 | 6 | export const TooltipSection = () => { 7 | const ref = useRef(null); 8 | const [shown, setShown] = useState(false); 9 | 10 | return ( 11 |
12 | 16 | 24 | 25 | {shown && ( 26 | 30 | Look in the mirror, you look so cute! Xx 31 | 32 | )} 33 |
34 | ); 35 | }; 36 | -------------------------------------------------------------------------------- /src/helpers/setBackgroundAsSecondary.ts: -------------------------------------------------------------------------------- 1 | import { getTelegramData } from '@telegram-apps/telegram-ui/dist/helpers/telegram'; 2 | 3 | export const setBackgroundAsSecondary = () => { 4 | const telegramData = getTelegramData(); 5 | if (!telegramData) { 6 | return; 7 | } 8 | 9 | telegramData.setBackgroundColor(telegramData.themeParams.secondary_bg_color); 10 | }; 11 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | background: var(--tg-theme-secondary-bg-color); 5 | } 6 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import '@telegram-apps/telegram-ui/dist/styles.css'; 2 | import './index.css'; 3 | 4 | import { createRoot } from 'react-dom/client'; 5 | import { App } from './App'; 6 | import { setBackgroundAsSecondary } from './helpers/setBackgroundAsSecondary'; 7 | 8 | setBackgroundAsSecondary(); 9 | 10 | const root = createRoot( 11 | document.getElementById('root') as HTMLElement 12 | ); 13 | 14 | root.render(); 15 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react-jsx", 4 | "target": "es5", 5 | "lib": [ 6 | "dom", 7 | "dom.iterable", 8 | "esnext" 9 | ], 10 | "allowJs": true, 11 | "skipLibCheck": true, 12 | "esModuleInterop": true, 13 | "allowSyntheticDefaultImports": true, 14 | "strict": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "noFallthroughCasesInSwitch": true, 17 | "module": "esnext", 18 | "moduleResolution": "node", 19 | "resolveJsonModule": true, 20 | "isolatedModules": true, 21 | "noEmit": true, 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | --------------------------------------------------------------------------------