mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-27 01:25:52 -05:00
Merge remote-tracking branch 'origin/develop' into release/2023-04-12
This commit is contained in:
commit
d4341879e4
14 changed files with 352 additions and 193 deletions
146
package-lock.json
generated
146
package-lock.json
generated
|
@ -21,7 +21,7 @@
|
|||
"react-twitter-embed": "^3.0.3",
|
||||
"react-use": "^17.3.1",
|
||||
"scratch-parser": "5.1.1",
|
||||
"scratch-storage": "2.2.0"
|
||||
"scratch-storage": "2.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@formatjs/intl-datetimeformat": "6.4.3",
|
||||
|
@ -101,8 +101,8 @@
|
|||
"regenerator-runtime": "0.13.9",
|
||||
"sass": "1.49.7",
|
||||
"sass-loader": "10.2.1",
|
||||
"scratch-gui": "1.8.0",
|
||||
"scratch-l10n": "3.15.20230327032134",
|
||||
"scratch-gui": "1.8.21",
|
||||
"scratch-l10n": "3.15.20230412032123",
|
||||
"selenium-webdriver": "4.1.0",
|
||||
"slick-carousel": "1.6.0",
|
||||
"style-loader": "0.12.3",
|
||||
|
@ -23463,21 +23463,21 @@
|
|||
}
|
||||
},
|
||||
"node_modules/scratch-blocks": {
|
||||
"version": "0.1.0-prerelease.20230326090609",
|
||||
"resolved": "https://registry.npmjs.org/scratch-blocks/-/scratch-blocks-0.1.0-prerelease.20230326090609.tgz",
|
||||
"integrity": "sha512-xzUHK3P98uUlwZonIW/kz9KYMxwvGpwocT8t/QFXEUsQpGIWuVMVDD8GiyKmtPN4ZhtNd/BjQSpa+Uv9wRwmcg==",
|
||||
"version": "0.1.0-prerelease.20230412165437",
|
||||
"resolved": "https://registry.npmjs.org/scratch-blocks/-/scratch-blocks-0.1.0-prerelease.20230412165437.tgz",
|
||||
"integrity": "sha512-sxdCHrKPUnQyigL8EX20AsztjOitVo5ruQCwUNwLQeCVS1HaBWo3LyE2E6E6QMsnPsS81Z5UeqM5z+9W2hjyeQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"exports-loader": "0.7.0",
|
||||
"google-closure-library": "20190301.0.0",
|
||||
"imports-loader": "0.8.0",
|
||||
"scratch-l10n": "3.15.20230326032128"
|
||||
"scratch-l10n": "3.15.20230410032122"
|
||||
}
|
||||
},
|
||||
"node_modules/scratch-blocks/node_modules/scratch-l10n": {
|
||||
"version": "3.15.20230326032128",
|
||||
"resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230326032128.tgz",
|
||||
"integrity": "sha512-eGs59KH1J+K+e1QW1fU3kudoW1GGboT7cdJoXoT5O524WSvnl2SwSaEYI1jt3mO03Za7fMy2OYTlx4W2x7UcKQ==",
|
||||
"version": "3.15.20230410032122",
|
||||
"resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230410032122.tgz",
|
||||
"integrity": "sha512-XUJZIG9GAh5ePB+xszRpdzqAD3nPaAxNwOdM+bnxALq/2rk9mieFF4/6vaE3+t8Yigbt0/CPsy5Y2weLTrKVOQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/cli": "^7.1.2",
|
||||
|
@ -23493,9 +23493,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/scratch-gui": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-1.8.0.tgz",
|
||||
"integrity": "sha512-FFyUEBGVVO8yKZcp/tv8kn5/C9tVhbimK+WvUkTYrswZ3HLz8mqpgXmM7shYKwb03pqv1uxpU/XwiU9OSur5Yw==",
|
||||
"version": "1.8.21",
|
||||
"resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-1.8.21.tgz",
|
||||
"integrity": "sha512-/XF1V1zt9D3EDw1Po6WIRXEDunbatHoK4hDoRJN+VMh0F+4MCCBsmdNOUecsESAp6H4NeAWv5iXxfInpCU8WWg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"arraybuffer-loader": "^1.0.6",
|
||||
|
@ -23547,14 +23547,14 @@
|
|||
"redux": "3.7.2",
|
||||
"redux-throttle": "0.1.1",
|
||||
"scratch-audio": "0.1.0-prerelease.20221123180128",
|
||||
"scratch-blocks": "0.1.0-prerelease.20230326090609",
|
||||
"scratch-l10n": "3.15.20230326032128",
|
||||
"scratch-paint": "1.1.38",
|
||||
"scratch-blocks": "0.1.0-prerelease.20230412165437",
|
||||
"scratch-l10n": "3.15.20230412032123",
|
||||
"scratch-paint": "1.1.46",
|
||||
"scratch-render": "0.1.0-prerelease.20230318150639",
|
||||
"scratch-render-fonts": "1.0.0-prerelease.20221102164332",
|
||||
"scratch-storage": "2.2.0",
|
||||
"scratch-storage": "2.2.1",
|
||||
"scratch-svg-renderer": "0.2.0-prerelease.20230224194137",
|
||||
"scratch-vm": "1.5.10",
|
||||
"scratch-vm": "1.5.29",
|
||||
"startaudiocontext": "1.2.1",
|
||||
"style-loader": "^0.23.0",
|
||||
"text-encoding": "0.7.0",
|
||||
|
@ -23880,28 +23880,10 @@
|
|||
"symbol-observable": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/scratch-gui/node_modules/scratch-l10n": {
|
||||
"version": "3.15.20230326032128",
|
||||
"resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230326032128.tgz",
|
||||
"integrity": "sha512-eGs59KH1J+K+e1QW1fU3kudoW1GGboT7cdJoXoT5O524WSvnl2SwSaEYI1jt3mO03Za7fMy2OYTlx4W2x7UcKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/cli": "^7.1.2",
|
||||
"@babel/core": "^7.1.2",
|
||||
"@transifex/api": "4.2.5",
|
||||
"babel-plugin-react-intl": "^3.0.1",
|
||||
"download": "^8.0.0",
|
||||
"transifex": "1.6.6"
|
||||
},
|
||||
"bin": {
|
||||
"build-i18n-src": "scripts/build-i18n-src.js",
|
||||
"tx-push-src": "scripts/tx-push-src.js"
|
||||
}
|
||||
},
|
||||
"node_modules/scratch-gui/node_modules/scratch-paint": {
|
||||
"version": "1.1.38",
|
||||
"resolved": "https://registry.npmjs.org/scratch-paint/-/scratch-paint-1.1.38.tgz",
|
||||
"integrity": "sha512-fB/ltIMqkIWq68LtzhES+RxaK8eetwwOU2ZsuPab5Ggy624lqpK6LHIPgr55FS8AGM5NNC9nD5jQVbdZ7EBzPQ==",
|
||||
"version": "1.1.46",
|
||||
"resolved": "https://registry.npmjs.org/scratch-paint/-/scratch-paint-1.1.46.tgz",
|
||||
"integrity": "sha512-uklJlBvb9dGt1A50kEp1TZ3hWS1dZWWoL7+l7gIR6eILSglmcO0iqPCfDoy9lB4AybaMIDs9goDOqmq+mAZ2Sg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@scratch/paper": "0.11.20200728195508",
|
||||
|
@ -23980,9 +23962,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/scratch-l10n": {
|
||||
"version": "3.15.20230327032134",
|
||||
"resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230327032134.tgz",
|
||||
"integrity": "sha512-5Y5F+vXEqz1GVqJ2IRsQCjyrJV7f99akFSIwfXBdSfty1h8KUP9K+RhDz8zZaXzeZq/SlMLM0LMsrG0KQSyTuA==",
|
||||
"version": "3.15.20230412032123",
|
||||
"resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230412032123.tgz",
|
||||
"integrity": "sha512-k0X6Xf0u7CBUMMvzryhlcpL96Lhqx4qkot7A6gyLcOJ6WmfmfeM/xHvThA5AI3QT7tB2HMBeAKUx/ST4p2z5eg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/cli": "^7.1.2",
|
||||
|
@ -24111,9 +24093,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/scratch-storage": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/scratch-storage/-/scratch-storage-2.2.0.tgz",
|
||||
"integrity": "sha512-d2DzApJ9cSlQ42/cEKDD/lfYIocHMskWrOQ5VED6tKgiHirjRZSPflUIfWL8lY5LxE3HSBc/Z7pS3Yvqe/iCGA==",
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/scratch-storage/-/scratch-storage-2.2.1.tgz",
|
||||
"integrity": "sha512-qogGcWBXqKUHgfvSgyUkos4fuj7z+SDDHBVlT3NNC4gtZgw4dq+USwHjKXCwtRs6BN/joI7+LafFJtSLii6G/w==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.21.0",
|
||||
"arraybuffer-loader": "^1.0.3",
|
||||
|
@ -24182,9 +24164,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/scratch-vm": {
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/scratch-vm/-/scratch-vm-1.5.10.tgz",
|
||||
"integrity": "sha512-XHRxoTBWKIBymLqcelAeYdIJz6i7t/Av6Z7nOH1nCHourR1mvNs23Xk7ospFu9LVDTtLGVq9LkKgckqsG8SKuA==",
|
||||
"version": "1.5.29",
|
||||
"resolved": "https://registry.npmjs.org/scratch-vm/-/scratch-vm-1.5.29.tgz",
|
||||
"integrity": "sha512-vTDTPa8meaa8Nnz2VxA9rsQ6+avIcDVKQLTJocTxXy0C+ucrQkXBqpzSf5nObqwWSDKsZEpD4TtcReIx8b6BvQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@vernier/godirect": "1.5.0",
|
||||
|
@ -51963,21 +51945,21 @@
|
|||
}
|
||||
},
|
||||
"scratch-blocks": {
|
||||
"version": "0.1.0-prerelease.20230326090609",
|
||||
"resolved": "https://registry.npmjs.org/scratch-blocks/-/scratch-blocks-0.1.0-prerelease.20230326090609.tgz",
|
||||
"integrity": "sha512-xzUHK3P98uUlwZonIW/kz9KYMxwvGpwocT8t/QFXEUsQpGIWuVMVDD8GiyKmtPN4ZhtNd/BjQSpa+Uv9wRwmcg==",
|
||||
"version": "0.1.0-prerelease.20230412165437",
|
||||
"resolved": "https://registry.npmjs.org/scratch-blocks/-/scratch-blocks-0.1.0-prerelease.20230412165437.tgz",
|
||||
"integrity": "sha512-sxdCHrKPUnQyigL8EX20AsztjOitVo5ruQCwUNwLQeCVS1HaBWo3LyE2E6E6QMsnPsS81Z5UeqM5z+9W2hjyeQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"exports-loader": "0.7.0",
|
||||
"google-closure-library": "20190301.0.0",
|
||||
"imports-loader": "0.8.0",
|
||||
"scratch-l10n": "3.15.20230326032128"
|
||||
"scratch-l10n": "3.15.20230410032122"
|
||||
},
|
||||
"dependencies": {
|
||||
"scratch-l10n": {
|
||||
"version": "3.15.20230326032128",
|
||||
"resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230326032128.tgz",
|
||||
"integrity": "sha512-eGs59KH1J+K+e1QW1fU3kudoW1GGboT7cdJoXoT5O524WSvnl2SwSaEYI1jt3mO03Za7fMy2OYTlx4W2x7UcKQ==",
|
||||
"version": "3.15.20230410032122",
|
||||
"resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230410032122.tgz",
|
||||
"integrity": "sha512-XUJZIG9GAh5ePB+xszRpdzqAD3nPaAxNwOdM+bnxALq/2rk9mieFF4/6vaE3+t8Yigbt0/CPsy5Y2weLTrKVOQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/cli": "^7.1.2",
|
||||
|
@ -51991,9 +51973,9 @@
|
|||
}
|
||||
},
|
||||
"scratch-gui": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-1.8.0.tgz",
|
||||
"integrity": "sha512-FFyUEBGVVO8yKZcp/tv8kn5/C9tVhbimK+WvUkTYrswZ3HLz8mqpgXmM7shYKwb03pqv1uxpU/XwiU9OSur5Yw==",
|
||||
"version": "1.8.21",
|
||||
"resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-1.8.21.tgz",
|
||||
"integrity": "sha512-/XF1V1zt9D3EDw1Po6WIRXEDunbatHoK4hDoRJN+VMh0F+4MCCBsmdNOUecsESAp6H4NeAWv5iXxfInpCU8WWg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"arraybuffer-loader": "^1.0.6",
|
||||
|
@ -52045,14 +52027,14 @@
|
|||
"redux": "3.7.2",
|
||||
"redux-throttle": "0.1.1",
|
||||
"scratch-audio": "0.1.0-prerelease.20221123180128",
|
||||
"scratch-blocks": "0.1.0-prerelease.20230326090609",
|
||||
"scratch-l10n": "3.15.20230326032128",
|
||||
"scratch-paint": "1.1.38",
|
||||
"scratch-blocks": "0.1.0-prerelease.20230412165437",
|
||||
"scratch-l10n": "3.15.20230412032123",
|
||||
"scratch-paint": "1.1.46",
|
||||
"scratch-render": "0.1.0-prerelease.20230318150639",
|
||||
"scratch-render-fonts": "1.0.0-prerelease.20221102164332",
|
||||
"scratch-storage": "2.2.0",
|
||||
"scratch-storage": "2.2.1",
|
||||
"scratch-svg-renderer": "0.2.0-prerelease.20230224194137",
|
||||
"scratch-vm": "1.5.10",
|
||||
"scratch-vm": "1.5.29",
|
||||
"startaudiocontext": "1.2.1",
|
||||
"style-loader": "^0.23.0",
|
||||
"text-encoding": "0.7.0",
|
||||
|
@ -52316,24 +52298,10 @@
|
|||
"symbol-observable": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"scratch-l10n": {
|
||||
"version": "3.15.20230326032128",
|
||||
"resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230326032128.tgz",
|
||||
"integrity": "sha512-eGs59KH1J+K+e1QW1fU3kudoW1GGboT7cdJoXoT5O524WSvnl2SwSaEYI1jt3mO03Za7fMy2OYTlx4W2x7UcKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/cli": "^7.1.2",
|
||||
"@babel/core": "^7.1.2",
|
||||
"@transifex/api": "4.2.5",
|
||||
"babel-plugin-react-intl": "^3.0.1",
|
||||
"download": "^8.0.0",
|
||||
"transifex": "1.6.6"
|
||||
}
|
||||
},
|
||||
"scratch-paint": {
|
||||
"version": "1.1.38",
|
||||
"resolved": "https://registry.npmjs.org/scratch-paint/-/scratch-paint-1.1.38.tgz",
|
||||
"integrity": "sha512-fB/ltIMqkIWq68LtzhES+RxaK8eetwwOU2ZsuPab5Ggy624lqpK6LHIPgr55FS8AGM5NNC9nD5jQVbdZ7EBzPQ==",
|
||||
"version": "1.1.46",
|
||||
"resolved": "https://registry.npmjs.org/scratch-paint/-/scratch-paint-1.1.46.tgz",
|
||||
"integrity": "sha512-uklJlBvb9dGt1A50kEp1TZ3hWS1dZWWoL7+l7gIR6eILSglmcO0iqPCfDoy9lB4AybaMIDs9goDOqmq+mAZ2Sg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@scratch/paper": "0.11.20200728195508",
|
||||
|
@ -52394,9 +52362,9 @@
|
|||
}
|
||||
},
|
||||
"scratch-l10n": {
|
||||
"version": "3.15.20230327032134",
|
||||
"resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230327032134.tgz",
|
||||
"integrity": "sha512-5Y5F+vXEqz1GVqJ2IRsQCjyrJV7f99akFSIwfXBdSfty1h8KUP9K+RhDz8zZaXzeZq/SlMLM0LMsrG0KQSyTuA==",
|
||||
"version": "3.15.20230412032123",
|
||||
"resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230412032123.tgz",
|
||||
"integrity": "sha512-k0X6Xf0u7CBUMMvzryhlcpL96Lhqx4qkot7A6gyLcOJ6WmfmfeM/xHvThA5AI3QT7tB2HMBeAKUx/ST4p2z5eg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/cli": "^7.1.2",
|
||||
|
@ -52521,9 +52489,9 @@
|
|||
}
|
||||
},
|
||||
"scratch-storage": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/scratch-storage/-/scratch-storage-2.2.0.tgz",
|
||||
"integrity": "sha512-d2DzApJ9cSlQ42/cEKDD/lfYIocHMskWrOQ5VED6tKgiHirjRZSPflUIfWL8lY5LxE3HSBc/Z7pS3Yvqe/iCGA==",
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/scratch-storage/-/scratch-storage-2.2.1.tgz",
|
||||
"integrity": "sha512-qogGcWBXqKUHgfvSgyUkos4fuj7z+SDDHBVlT3NNC4gtZgw4dq+USwHjKXCwtRs6BN/joI7+LafFJtSLii6G/w==",
|
||||
"requires": {
|
||||
"@babel/runtime": "7.21.0",
|
||||
"arraybuffer-loader": "^1.0.3",
|
||||
|
@ -52593,9 +52561,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"scratch-vm": {
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/scratch-vm/-/scratch-vm-1.5.10.tgz",
|
||||
"integrity": "sha512-XHRxoTBWKIBymLqcelAeYdIJz6i7t/Av6Z7nOH1nCHourR1mvNs23Xk7ospFu9LVDTtLGVq9LkKgckqsG8SKuA==",
|
||||
"version": "1.5.29",
|
||||
"resolved": "https://registry.npmjs.org/scratch-vm/-/scratch-vm-1.5.29.tgz",
|
||||
"integrity": "sha512-vTDTPa8meaa8Nnz2VxA9rsQ6+avIcDVKQLTJocTxXy0C+ucrQkXBqpzSf5nObqwWSDKsZEpD4TtcReIx8b6BvQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@vernier/godirect": "1.5.0",
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
"react-twitter-embed": "^3.0.3",
|
||||
"react-use": "^17.3.1",
|
||||
"scratch-parser": "5.1.1",
|
||||
"scratch-storage": "2.2.0"
|
||||
"scratch-storage": "2.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@formatjs/intl-datetimeformat": "6.4.3",
|
||||
|
@ -136,8 +136,8 @@
|
|||
"regenerator-runtime": "0.13.9",
|
||||
"sass": "1.49.7",
|
||||
"sass-loader": "10.2.1",
|
||||
"scratch-gui": "1.8.0",
|
||||
"scratch-l10n": "3.15.20230327032134",
|
||||
"scratch-gui": "1.8.21",
|
||||
"scratch-l10n": "3.15.20230412032123",
|
||||
"selenium-webdriver": "4.1.0",
|
||||
"slick-carousel": "1.6.0",
|
||||
"style-loader": "0.12.3",
|
||||
|
|
|
@ -20,7 +20,8 @@ const TTTModal = props => (
|
|||
'cardsUrl',
|
||||
'guideUrl',
|
||||
'thumbImage',
|
||||
'modalImage'
|
||||
'modalImage',
|
||||
'modalImageDescription'
|
||||
]
|
||||
)}
|
||||
>
|
||||
|
@ -29,7 +30,7 @@ const TTTModal = props => (
|
|||
<a href={props.tutorialUrl}>
|
||||
<div className="ttt-img-container">
|
||||
<img
|
||||
alt=""
|
||||
alt={props.modalImageDescription}
|
||||
className="mod-ttt-img"
|
||||
src={props.modalImage}
|
||||
/>
|
||||
|
@ -91,6 +92,7 @@ TTTModal.propTypes = {
|
|||
description: PropTypes.string.isRequired,
|
||||
guideUrl: PropTypes.string.isRequired,
|
||||
modalImage: PropTypes.string.isRequired,
|
||||
modalImageDescription: PropTypes.string,
|
||||
thumbImage: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
tutorialUrl: PropTypes.string.isRequired
|
||||
|
|
|
@ -20,6 +20,7 @@ const SubNavigation = props => (
|
|||
'sub-nav-align-right': props.align === 'right'
|
||||
}
|
||||
)}
|
||||
role={props.role}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
|
@ -27,6 +28,7 @@ const SubNavigation = props => (
|
|||
|
||||
SubNavigation.propTypes = {
|
||||
align: PropTypes.string,
|
||||
role: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
className: PropTypes.string
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const classNames = require('classnames');
|
||||
const PropTypes = require('prop-types');
|
||||
const {useRef} = require('react');
|
||||
const React = require('react');
|
||||
|
||||
const SubNavigation = require('../../components/subnavigation/subnavigation.jsx');
|
||||
|
@ -10,17 +10,94 @@ require('./tabs.scss');
|
|||
* Container for a custom, horizontal list of navigation elements
|
||||
* that can be displayed within a view or component.
|
||||
*/
|
||||
const Tabs = props => (
|
||||
<div className="tab-background">
|
||||
<SubNavigation className={classNames('tabs', props.className)}>
|
||||
{props.children}
|
||||
</SubNavigation>
|
||||
</div>
|
||||
);
|
||||
const Tabs = ({items, activeTabName}) => {
|
||||
const tabElementRefs = useRef({});
|
||||
|
||||
const itemsRendered = items.map(({name, onTrigger, getContent}) => {
|
||||
const isActive = name === activeTabName;
|
||||
|
||||
let tabRef;
|
||||
if (tabElementRefs.current[name]) {
|
||||
tabRef = tabElementRefs.current[name];
|
||||
} else {
|
||||
tabRef = React.createRef();
|
||||
tabElementRefs.current[name] = tabRef;
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={`${isActive ? 'true' : 'false'}`}
|
||||
className={`${isActive ? 'active' : ''}`}
|
||||
onClick={onTrigger}
|
||||
tabIndex={isActive ? 0 : -1}
|
||||
key={name}
|
||||
ref={tabRef}
|
||||
>
|
||||
{getContent(isActive)}
|
||||
</button>
|
||||
);
|
||||
});
|
||||
|
||||
const handleKeyDown = event => {
|
||||
if (!['ArrowLeft', 'ArrowRight', 'Home', 'End', 'Enter', ' '].includes(event.key)) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
const focusedIndex = Object.values(tabElementRefs.current)
|
||||
.findIndex(tabElementRef =>
|
||||
document.activeElement === tabElementRef.current
|
||||
);
|
||||
if (event.key === 'ArrowLeft') {
|
||||
let nextIndex;
|
||||
if (focusedIndex === 0) {
|
||||
nextIndex = Object.values(tabElementRefs.current).length - 1;
|
||||
} else {
|
||||
nextIndex = focusedIndex - 1;
|
||||
}
|
||||
Object.values(tabElementRefs.current)[nextIndex].current.focus();
|
||||
} else if (event.key === 'ArrowRight') {
|
||||
let nextIndex;
|
||||
if (focusedIndex === Object.values(tabElementRefs.current).length - 1) {
|
||||
nextIndex = 0;
|
||||
} else {
|
||||
nextIndex = focusedIndex + 1;
|
||||
}
|
||||
Object.values(tabElementRefs.current)[nextIndex].current.focus();
|
||||
} else if (event.key === 'Home') {
|
||||
Object.values(tabElementRefs.current)[0].current.focus();
|
||||
} else if (event.key === 'End') {
|
||||
const lastTab = Object.values(tabElementRefs.current).length - 1;
|
||||
Object.values(tabElementRefs.current)[lastTab].current.focus();
|
||||
} else if (event.key === 'Enter' || event.key === ' ') {
|
||||
items[focusedIndex].onTrigger();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className="tab-background"
|
||||
onKeyDown={handleKeyDown}// eslint-disable-line
|
||||
>
|
||||
<SubNavigation
|
||||
role="tablist"
|
||||
className="tabs"
|
||||
>
|
||||
{itemsRendered}
|
||||
</SubNavigation>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Tabs.propTypes = {
|
||||
children: PropTypes.node,
|
||||
className: PropTypes.string
|
||||
items: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
name: PropTypes.string.isRequired,
|
||||
onTrigger: PropTypes.func.isRequired,
|
||||
getContent: PropTypes.func.isRequired
|
||||
})
|
||||
).isRequired,
|
||||
activeTabName: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
module.exports = Tabs;
|
||||
|
|
|
@ -14,13 +14,14 @@
|
|||
justify-content: center;
|
||||
}
|
||||
|
||||
.tabs li {
|
||||
.tabs button {
|
||||
margin: 0;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
width: $cols2;
|
||||
text-align: center;
|
||||
color: $header-gray;
|
||||
background-color: transparent;
|
||||
|
||||
&.active {
|
||||
border-bottom: 3px solid $ui-aqua;
|
||||
|
|
|
@ -13,7 +13,7 @@ const TTTTile = props => (
|
|||
<div className="ttt-tile-tutorial">
|
||||
<div className="ttt-tile-image">
|
||||
<img
|
||||
alt=""
|
||||
alt={props.thumbImageDescription}
|
||||
className="ttt-tile-image-img"
|
||||
src={props.thumbImage}
|
||||
/>
|
||||
|
@ -33,6 +33,7 @@ TTTTile.propTypes = {
|
|||
description: PropTypes.string,
|
||||
onClick: PropTypes.func,
|
||||
thumbImage: PropTypes.string.isRequired,
|
||||
thumbImageDescription: PropTypes.string,
|
||||
title: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
|
|
|
@ -74,6 +74,8 @@
|
|||
"general.download": "Download",
|
||||
"general.password": "Password",
|
||||
"general.press": "Press",
|
||||
"general.projectsSelected": "Projects Tab Selected",
|
||||
"general.projectsNotS": "Projects",
|
||||
"general.privacyPolicy": "Privacy Policy",
|
||||
"general.projects": "Projects",
|
||||
"general.profile": "Profile",
|
||||
|
@ -91,6 +93,8 @@
|
|||
"general.startOver": "Start over",
|
||||
"general.statistics": "Statistics",
|
||||
"general.studios": "Studios",
|
||||
"general.studiosSelected": "Studios Tab Selected",
|
||||
"general.studiosNotS": "Studios",
|
||||
"general.support": "Resources",
|
||||
"general.ideas": "Ideas",
|
||||
"general.tipsWindow": "Tips Window",
|
||||
|
@ -111,13 +115,21 @@
|
|||
"general.seeAllComments": "See all comments",
|
||||
|
||||
"general.all": "All",
|
||||
"general.allSelected": "All Selected",
|
||||
"general.animations": "Animations",
|
||||
"general.animationsSelected": "Animations Selected",
|
||||
"general.art": "Art",
|
||||
"general.artSelected": "Art Selected",
|
||||
"general.games": "Games",
|
||||
"general.gamesSelected": "Games Selected",
|
||||
"general.music": "Music",
|
||||
"general.musicSelected": "Music Selected",
|
||||
"general.results": "Results",
|
||||
"general.resultsSelected": "Results Selected",
|
||||
"general.stories": "Stories",
|
||||
"general.storiesSelected": "Stories Selected",
|
||||
"general.tutorials": "Tutorials",
|
||||
"general.tutorialsSelected": "Tutorials Selected",
|
||||
|
||||
"general.teacherAccounts": "Teacher Accounts",
|
||||
|
||||
|
|
|
@ -26,10 +26,8 @@ class Explore extends React.Component {
|
|||
bindAll(this, [
|
||||
'getExploreState',
|
||||
'handleGetExploreMore',
|
||||
'changeItemType',
|
||||
'handleChangeSortMode',
|
||||
'getBubble',
|
||||
'getTab'
|
||||
'getBubble'
|
||||
]);
|
||||
|
||||
this.state = this.getExploreState();
|
||||
|
@ -96,16 +94,7 @@ class Explore extends React.Component {
|
|||
}
|
||||
});
|
||||
}
|
||||
changeItemType () {
|
||||
let newType;
|
||||
for (const t of this.state.acceptableTypes) {
|
||||
if (this.state.itemType !== t) {
|
||||
newType = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
window.location = `${window.location.origin}/explore/${newType}/${this.state.tab}/${this.state.mode}`;
|
||||
}
|
||||
|
||||
handleChangeSortMode (name, value) {
|
||||
if (this.state.acceptableModes.indexOf(value) !== -1) {
|
||||
window.location =
|
||||
|
@ -124,31 +113,7 @@ class Explore extends React.Component {
|
|||
</a>
|
||||
);
|
||||
}
|
||||
getTab (type) {
|
||||
const classes = classNames({
|
||||
active: (this.state.itemType === type)
|
||||
});
|
||||
return (
|
||||
<a href={`/explore/${type}/${this.state.category}/${this.state.mode}`}>
|
||||
<li className={classes}>
|
||||
{this.state.itemType === type ? [
|
||||
<img
|
||||
className={`tab-icon ${type}`}
|
||||
key={`tab-${type}`}
|
||||
src={`/svgs/tabs/${type}-active.svg`}
|
||||
/>
|
||||
] : [
|
||||
<img
|
||||
className={`tab-icon ${type}`}
|
||||
key={`tab-${type}`}
|
||||
src={`/svgs/tabs/${type}-inactive.svg`}
|
||||
/>
|
||||
]}
|
||||
<FormattedMessage id={`general.${type}`} />
|
||||
</li>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
|
@ -160,10 +125,63 @@ class Explore extends React.Component {
|
|||
</h1>
|
||||
</div>
|
||||
</TitleBanner>
|
||||
<Tabs>
|
||||
{this.getTab('projects')}
|
||||
{this.getTab('studios')}
|
||||
</Tabs>
|
||||
<Tabs
|
||||
items={[
|
||||
{
|
||||
name: 'projects',
|
||||
onTrigger: () => {
|
||||
window.location = `${window.location.origin}/explore/projects/` +
|
||||
`${this.state.category}/${this.state.mode}`;
|
||||
},
|
||||
getContent: isActive => (
|
||||
<div>
|
||||
{isActive ? (
|
||||
<img
|
||||
className="tab-icon projects"
|
||||
src="/svgs/tabs/projects-active.svg"
|
||||
alt=""
|
||||
/>
|
||||
) : (
|
||||
<img
|
||||
className="tab-icon projects"
|
||||
src="/svgs/tabs/projects-inactive.svg"
|
||||
alt=""
|
||||
/>
|
||||
)
|
||||
}
|
||||
<FormattedMessage id="general.projects" />
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: 'studios',
|
||||
onTrigger: () => {
|
||||
window.location = `${window.location.origin}/explore/studios/` +
|
||||
`${this.state.category}/${this.state.mode}`;
|
||||
},
|
||||
getContent: isActive => (
|
||||
<div>
|
||||
{isActive ? (
|
||||
<img
|
||||
className="tab-icon studios"
|
||||
src="/svgs/tabs/studios-active.svg"
|
||||
alt=""
|
||||
/>
|
||||
) : (
|
||||
<img
|
||||
className="tab-icon studios"
|
||||
src="/svgs/tabs/studios-inactive.svg"
|
||||
alt=""
|
||||
/>
|
||||
)
|
||||
}
|
||||
<FormattedMessage id="general.studios" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
]}
|
||||
activeTabName={this.state.itemType}
|
||||
/>
|
||||
<div className="sort-controls">
|
||||
<SubNavigation className="categories">
|
||||
{this.getBubble('all')}
|
||||
|
|
|
@ -48,9 +48,11 @@ class Ideas extends React.Component {
|
|||
const translatedTile = {
|
||||
tutorialUrl: `/projects/editor/?tutorial=${tile.tutorialUrl}`,
|
||||
modalImage: tile.modalImage,
|
||||
modalImageDescription: this.props.intl.formatMessage({id: tile.modalImageDescription}),
|
||||
description: this.props.intl.formatMessage({id: tile.description}),
|
||||
guideUrl: this.props.intl.formatMessage({id: tile.guideUrl}),
|
||||
thumbImage: tile.thumbImage,
|
||||
thumbImageDescription: this.props.intl.formatMessage({id: tile.thumbImageDescription}),
|
||||
title: this.props.intl.formatMessage({id: tile.title}),
|
||||
cardsUrl: this.props.intl.formatMessage({id: tile.cardsUrl})
|
||||
};
|
||||
|
@ -71,13 +73,19 @@ class Ideas extends React.Component {
|
|||
<div className="banner-wrapper">
|
||||
<TitleBanner className="masthead ideas-banner">
|
||||
<div className="title-banner-p">
|
||||
<img src="/images/ideas/masthead-illustration.svg" />
|
||||
<img
|
||||
alt={this.props.intl.formatMessage({id: 'ideas.headerImageDescription'})}
|
||||
src="/images/ideas/masthead-illustration.svg"
|
||||
/>
|
||||
<h1 className="title-banner-h1">
|
||||
<FormattedMessage id="ideas.headerMessage" />
|
||||
</h1>
|
||||
<a href="/projects/editor/?tutorial=all">
|
||||
<Button className="ideas-button">
|
||||
<img src="/images/ideas/bulb-icon.svg" />
|
||||
<img
|
||||
alt=""
|
||||
src="/images/ideas/bulb-icon.svg"
|
||||
/>
|
||||
<FormattedMessage id="ideas.headerButtonMessage" />
|
||||
</Button>
|
||||
</a>
|
||||
|
@ -91,7 +99,10 @@ class Ideas extends React.Component {
|
|||
className="tips-info-section tips-left"
|
||||
>
|
||||
<div className="ideas-image">
|
||||
<img src="/images/ideas/getting-started-illustration.svg" />
|
||||
<img
|
||||
alt={this.props.intl.formatMessage({id: 'ideas.gettingStartedImageDescription'})}
|
||||
src="/images/ideas/getting-started-illustration.svg"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h2>
|
||||
|
@ -102,7 +113,10 @@ class Ideas extends React.Component {
|
|||
</p>
|
||||
<a href="/projects/editor/?tutorial=getStarted">
|
||||
<Button className="ideas-button">
|
||||
<img src="/images/ideas/try-it-icon.svg" />
|
||||
<img
|
||||
alt=""
|
||||
src="/images/ideas/try-it-icon.svg"
|
||||
/>
|
||||
<FormattedMessage id="ideas.tryIt" />
|
||||
</Button>
|
||||
</a>
|
||||
|
@ -161,13 +175,19 @@ class Ideas extends React.Component {
|
|||
target="_blank"
|
||||
>
|
||||
<Button className="ideas-button">
|
||||
<img src="/images/ideas/download-icon.svg" />
|
||||
<img
|
||||
alt=""
|
||||
src="/images/ideas/download-icon.svg"
|
||||
/>
|
||||
<FormattedMessage id="general.downloadPDF" />
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
<div className="tips-info-body tips-illustration">
|
||||
<img src="/images/ideas/cards-illustration.svg" />
|
||||
<img
|
||||
alt={this.props.intl.formatMessage({id: 'ideas.cardsIllustrationDescription'})}
|
||||
src="/images/ideas/cards-illustration.svg"
|
||||
/>
|
||||
</div>
|
||||
</FlexRow>
|
||||
</div>
|
||||
|
@ -183,6 +203,7 @@ class Ideas extends React.Component {
|
|||
>
|
||||
<div className="ideas-image">
|
||||
<img
|
||||
alt={this.props.intl.formatMessage({id: 'ideas.starterProjectsImageDescription'})}
|
||||
src="/images/ideas/starter-projects-illustration.svg"
|
||||
/>
|
||||
</div>
|
||||
|
@ -213,6 +234,7 @@ class Ideas extends React.Component {
|
|||
<div className="tips-info-body mod-narrow">
|
||||
<img
|
||||
className="tips-icon"
|
||||
alt=""
|
||||
src="/images/tips/download-icon.svg"
|
||||
/>
|
||||
<h3>
|
||||
|
@ -228,6 +250,7 @@ class Ideas extends React.Component {
|
|||
<div className="tips-info-body mod-narrow">
|
||||
<img
|
||||
className="tips-icon"
|
||||
alt=""
|
||||
src="/images/tips/question-icon.svg"
|
||||
/>
|
||||
<h3>
|
||||
|
|
|
@ -1,28 +1,38 @@
|
|||
{
|
||||
"ideas.headerMessage": "What will you create?",
|
||||
"ideas.headerImageDescription": "Outlandish creations from pixelated unicorns to drumbeat waveforms to levitating tacos to buckets of rainbows.",
|
||||
"ideas.headerButtonMessage": "Choose a tutorial",
|
||||
"ideas.gettingStartedTitle": "Getting Started",
|
||||
"ideas.gettingStartedText": "New to Scratch? Try the Getting Started tutorial.",
|
||||
"ideas.gettingStartedImageDescription": "An illustrated boy plants his flag on top of a freshly painted mountaintop.",
|
||||
"ideas.tryIt": "Try it!",
|
||||
"ideas.activityGuidesTitle": "Activity Guides",
|
||||
"ideas.activityGuidesText": "What do you want to make with Scratch? For each activity, you can try the Tutorial, download a set of Coding Cards, or view the Educator Guide.",
|
||||
"ideas.animateANameTitle": "Animate a Name",
|
||||
"ideas.animateANameDescription": "Animate the letters of your name, initials, or favorite word.",
|
||||
"ideas.animateANameImageDescription": "The name ANYA in all caps and blocked letters is poised to wiggle",
|
||||
"ideas.animateACharacterTitle": "Animate a Character",
|
||||
"ideas.animateACharacterDescription": "Bring characters to life with animation.",
|
||||
"ideas.animateACharacterImageDescription": "An taco with a wand, wizard cap and flowing white beard floats enchantingly in low-Earth orbit.",
|
||||
"ideas.makeMusicTitle": "Make Music",
|
||||
"ideas.makeMusicDescription": "Choose instruments, add sounds, and press keys to play music.",
|
||||
"ideas.makeMusicImageDescription": "Strings vibrate on an illustrated Gibson explorer.",
|
||||
"ideas.createAStoryTitle": "Create a Story",
|
||||
"ideas.createAStoryDescription": "Choose characters, add conversation, and bring your story to life.",
|
||||
"ideas.createAStoryImageDescription": "A wizard beckons a traveling witch towards a distant castle.",
|
||||
"ideas.chaseGameTitle": "Make a Chase Game",
|
||||
"ideas.chaseGameDescription": "Make a game where you chase a character to score points.",
|
||||
"ideas.chaseGameImageDescription": "A happy interactive octopus passes over a star.",
|
||||
"ideas.videoSensingTitle": "Video Sensing",
|
||||
"ideas.videoSensingDescription": "Interact with a project using the Video Sensing extension.",
|
||||
"ideas.videoSensingImageDescription": "A virtual hand dodges a spurt of flame in an attempt to pet a dragon.",
|
||||
"ideas.seeAllTutorials": "See All Tutorials",
|
||||
"ideas.cardsTitle": "Get the Entire Collection of Coding Cards",
|
||||
"ideas.cardsText": "With the Scratch Coding Cards, you can learn to create interactive games, stories, music, animations, and more!",
|
||||
"ideas.cardsIllustrationDescription": "An assortment of fun, animated characters and objects leap out of a stack of cards.",
|
||||
"ideas.starterProjectsTitle": "Starter Projects",
|
||||
"ideas.starterProjectsText": "You can play with Starter Projects and remix them to make your own creations.",
|
||||
"ideas.starterProjectsImageDescription": "An illustration of the Scratch Code Editor.",
|
||||
"ideas.starterProjectsButton": "Explore Starter Projects",
|
||||
"ideas.tryTheTutorial": "Try the tutorial",
|
||||
"ideas.codingCards": "Coding Cards",
|
||||
|
@ -36,6 +46,7 @@
|
|||
"ideas.cardsPurchase": "Purchase Printed Set",
|
||||
"ideas.MakeItFlyTitle": "Make It Fly",
|
||||
"ideas.MakeItFlyDescription": "Choose any character and make it fly!",
|
||||
"ideas.MakeItFlyImageDescription": "The scratch cat flies over the skyline. Alongside a flying taco.",
|
||||
"ideas.RaceTitle": "Race to the Finish",
|
||||
"ideas.RaceDescription": "Make a game where two characters race each other.",
|
||||
"ideas.HideAndSeekTitle": "Hide and Seek",
|
||||
|
@ -44,8 +55,10 @@
|
|||
"ideas.FashionDescription": "Make a game where you dress a character with different clothes and styles.",
|
||||
"ideas.PongTitle": "Pong Game",
|
||||
"ideas.PongDescription": "Make a bouncing ball game with sounds, points, and other effects.",
|
||||
"ideas.PongImageDescription": "A ball bounces off a digital paddle.",
|
||||
"ideas.ImagineTitle": "Imagine a World",
|
||||
"ideas.ImagineDescription": "Imagine a world where anything is possible.",
|
||||
"ideas.ImagineImageDescription": "A girl stands proudly in front of a thought bubble as big as the Earth and as intricate as butterfly wings.",
|
||||
"ideas.DanceTitle": "Let's Dance",
|
||||
"ideas.DanceDescription": "Design an animated dance scene with music and dance moves.",
|
||||
"ideas.CatchTitle": "Catch Game",
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
"title": "ideas.animateANameTitle",
|
||||
"description": "ideas.animateANameDescription",
|
||||
"thumbImage": "/images/ideas/activities/animate-a-name-thumb.jpg",
|
||||
"thumbImageDescription": "ideas.animateANameImageDescription",
|
||||
"modalImage": "/images/ideas/activities/animate-a-name-modal.jpg",
|
||||
"modalImageDescription": "ideas.animateANameImageDescription",
|
||||
"tutorialUrl": "name",
|
||||
"cardsUrl": "cards.name-cardsLink",
|
||||
"guideUrl": "guides.NameGuideLink"
|
||||
|
@ -12,7 +14,9 @@
|
|||
"title": "ideas.ImagineTitle",
|
||||
"description": "ideas.ImagineDescription",
|
||||
"thumbImage": "/images/ideas/activities/imagine-thumb.jpg",
|
||||
"thumbImageDescription": "ideas.ImagineImageDescription",
|
||||
"modalImage": "/images/ideas/activities/imagine-modal.jpg",
|
||||
"modalImageDescription": "ideas.ImagineImageDescription",
|
||||
"tutorialUrl": "imagine",
|
||||
"cardsUrl": "cards.imagine-cardsLink",
|
||||
"guideUrl": "guides.ImagineGuideLink"
|
||||
|
@ -21,7 +25,9 @@
|
|||
"title": "ideas.chaseGameTitle",
|
||||
"description": "ideas.chaseGameDescription",
|
||||
"thumbImage": "/images/ideas/activities/chase-game-thumb.jpg",
|
||||
"thumbImageDescription": "ideas.chaseGameImageDescription",
|
||||
"modalImage": "/images/ideas/activities/chase-game-modal.jpg",
|
||||
"modalImageDescription": "ideas.chaseGameImageDescription",
|
||||
"tutorialUrl": "chase-game",
|
||||
"cardsUrl": "cards.chase-cardsLink",
|
||||
"guideUrl": "guides.ChaseGuideLink"
|
||||
|
@ -30,7 +36,9 @@
|
|||
"title": "ideas.makeMusicTitle",
|
||||
"description": "ideas.makeMusicDescription",
|
||||
"thumbImage": "/images/ideas/activities/make-music-thumb.jpg",
|
||||
"thumbImageDescription": "ideas.makeMusicImageDescription",
|
||||
"modalImage": "/images/ideas/activities/make-music-modal.jpg",
|
||||
"modalImageDescription": "ideas.makeMusicImageDescription",
|
||||
"tutorialUrl": "music",
|
||||
"cardsUrl": "cards.music-cardsLink",
|
||||
"guideUrl": "guides.MusicGuideLink"
|
||||
|
@ -39,7 +47,9 @@
|
|||
"title": "ideas.createAStoryTitle",
|
||||
"description": "ideas.createAStoryDescription",
|
||||
"thumbImage": "/images/ideas/activities/create-a-story-thumb.jpg",
|
||||
"thumbImageDescription": "ideas.createAStoryImageDescription",
|
||||
"modalImage": "/images/ideas/activities/create-a-story-modal.jpg",
|
||||
"modalImageDescription": "ideas.createAStoryImageDescription",
|
||||
"tutorialUrl": "tell-a-story",
|
||||
"cardsUrl": "cards.story-cardsLink",
|
||||
"guideUrl": "guides.StoryGuideLink"
|
||||
|
@ -48,7 +58,9 @@
|
|||
"title": "ideas.MakeItFlyTitle",
|
||||
"description": "ideas.MakeItFlyDescription",
|
||||
"thumbImage": "/images/ideas/activities/fly-thumb.jpg",
|
||||
"thumbImageDescription": "ideas.MakeItFlyImageDescription",
|
||||
"modalImage": "/images/ideas/activities/fly-modal.jpg",
|
||||
"modalImageDescription": "ideas.MakeItFlyImageDescription",
|
||||
"tutorialUrl": "make-it-fly",
|
||||
"cardsUrl": "cards.fly-cardsLink",
|
||||
"guideUrl": "guides.FlyGuideLink"
|
||||
|
@ -57,7 +69,9 @@
|
|||
"title": "ideas.PongTitle",
|
||||
"description": "ideas.PongDescription",
|
||||
"thumbImage": "/images/ideas/activities/pong-thumb.jpg",
|
||||
"thumbImageDescription": "ideas.PongImageDescription",
|
||||
"modalImage": "/images/ideas/activities/pong-modal.jpg",
|
||||
"modalImageDescription": "ideas.PongImageDescription",
|
||||
"tutorialUrl": "pong",
|
||||
"cardsUrl": "cards.pong-cardsLink",
|
||||
"guideUrl": "guides.PongGuideLink"
|
||||
|
@ -66,7 +80,9 @@
|
|||
"title": "ideas.animateACharacterTitle",
|
||||
"description": "ideas.animateACharacterDescription",
|
||||
"thumbImage": "/images/ideas/activities/animate-a-character-thumb.jpg",
|
||||
"thumbImageDescription": "ideas.animateACharacterImageDescription",
|
||||
"modalImage": "/images/ideas/activities/animate-a-character-modal.jpg",
|
||||
"modalImageDescription": "ideas.animateACharacterImageDescription",
|
||||
"tutorialUrl": "animate-a-character",
|
||||
"cardsUrl": "cards.animation-cardsLink",
|
||||
"guideUrl": "guides.AnimateGuideLink"
|
||||
|
@ -75,7 +91,9 @@
|
|||
"title": "ideas.videoSensingTitle",
|
||||
"description": "ideas.videoSensingDescription",
|
||||
"thumbImage": "/images/ideas/activities/video-sensing-thumb.jpg",
|
||||
"thumbImageDescription": "ideas.videoSensingImageDescription",
|
||||
"modalImage": "/images/ideas/activities/video-sensing-modal.jpg",
|
||||
"modalImageDescription": "ideas.videoSensingImageDescription",
|
||||
"tutorialUrl": "video-sensing",
|
||||
"cardsUrl": "cards.video-cardsLink",
|
||||
"guideUrl": "guides.VideoGuideLink"
|
||||
|
|
|
@ -31,8 +31,7 @@ class Search extends React.Component {
|
|||
bindAll(this, [
|
||||
'getSearchState',
|
||||
'handleChangeSortMode',
|
||||
'handleGetSearchMore',
|
||||
'getTab'
|
||||
'handleGetSearchMore'
|
||||
]);
|
||||
this.state = this.getSearchState();
|
||||
this.state.loaded = [];
|
||||
|
@ -151,38 +150,6 @@ class Search extends React.Component {
|
|||
});
|
||||
});
|
||||
}
|
||||
getTab (type) {
|
||||
const termText = this.encodeSearchTerm();
|
||||
let targetUrl = `/search/${type}`;
|
||||
if (termText) {
|
||||
targetUrl += `?q=${termText}`;
|
||||
}
|
||||
let allTab = (
|
||||
<a href={targetUrl}>
|
||||
<li>
|
||||
<img
|
||||
className={`tab-icon ${type}`}
|
||||
src={`/svgs/tabs/${type}-inactive.svg`}
|
||||
/>
|
||||
<FormattedMessage id={`general.${type}`} />
|
||||
</li>
|
||||
</a>
|
||||
);
|
||||
if (this.state.tab === type) {
|
||||
allTab = (
|
||||
<a href={targetUrl}>
|
||||
<li className="active">
|
||||
<img
|
||||
className={`tab-icon ${type}`}
|
||||
src={`/svgs/tabs/${type}-active.svg`}
|
||||
/>
|
||||
<FormattedMessage id={`general.${type}`} />
|
||||
</li>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
return allTab;
|
||||
}
|
||||
getProjectBox () {
|
||||
const results = (
|
||||
<Grid
|
||||
|
@ -228,10 +195,67 @@ class Search extends React.Component {
|
|||
</h1>
|
||||
</div>
|
||||
</TitleBanner>
|
||||
<Tabs>
|
||||
{this.getTab('projects')}
|
||||
{this.getTab('studios')}
|
||||
</Tabs>
|
||||
<Tabs
|
||||
items={[
|
||||
{
|
||||
name: 'projects',
|
||||
onTrigger: () => {
|
||||
const termText = this.encodeSearchTerm();
|
||||
let targetUrl = `/search/projects`;
|
||||
if (termText) targetUrl += `?q=${termText}`;
|
||||
window.location = targetUrl;
|
||||
},
|
||||
getContent: isActive => (
|
||||
<div>
|
||||
{isActive ? (
|
||||
<img
|
||||
className="tab-icon projects"
|
||||
src="/svgs/tabs/projects-active.svg"
|
||||
alt=""
|
||||
/>
|
||||
) : (
|
||||
<img
|
||||
className="tab-icon projects"
|
||||
src="/svgs/tabs/projects-inactive.svg"
|
||||
alt=""
|
||||
/>
|
||||
)
|
||||
}
|
||||
<FormattedMessage id="general.projects" />
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: 'studios',
|
||||
onTrigger: () => {
|
||||
const termText = this.encodeSearchTerm();
|
||||
let targetUrl = `/search/studios`;
|
||||
if (termText) targetUrl += `?q=${termText}`;
|
||||
window.location = targetUrl;
|
||||
},
|
||||
getContent: isActive => (
|
||||
<div>
|
||||
{isActive ? (
|
||||
<img
|
||||
className="tab-icon studios"
|
||||
src="/svgs/tabs/studios-active.svg"
|
||||
alt=""
|
||||
/>
|
||||
) : (
|
||||
<img
|
||||
className="tab-icon studios"
|
||||
src="/svgs/tabs/studios-inactive.svg"
|
||||
alt=""
|
||||
/>
|
||||
)
|
||||
}
|
||||
<FormattedMessage id="general.studios" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
]}
|
||||
activeTabName={this.state.tab}
|
||||
/>
|
||||
<div className="sort-controls">
|
||||
<Form className="sort-mode">
|
||||
<Select
|
||||
|
|
|
@ -1 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>Icons</title><path d="M13.39,3.29V9.4a0.41,0.41,0,0,1-.14.31,4.18,4.18,0,0,1-5.51,0,3.42,3.42,0,0,0-2.23-.84,3.35,3.35,0,0,0-2.07.72v4.05a0.42,0.42,0,1,1-.84,0V3.29A0.41,0.41,0,0,1,2.87,2.9,4.17,4.17,0,0,1,8.27,3a3.39,3.39,0,0,0,4.45,0,0.39,0.39,0,0,1,.43-0.06A0.4,0.4,0,0,1,13.39,3.29Z" fill="#26d9bb" stroke="#22b296" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
<svg aria-label="Check Check" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>Icons</title><path d="M13.39,3.29V9.4a0.41,0.41,0,0,1-.14.31,4.18,4.18,0,0,1-5.51,0,3.42,3.42,0,0,0-2.23-.84,3.35,3.35,0,0,0-2.07.72v4.05a0.42,0.42,0,1,1-.84,0V3.29A0.41,0.41,0,0,1,2.87,2.9,4.17,4.17,0,0,1,8.27,3a3.39,3.39,0,0,0,4.45,0,0.39,0.39,0,0,1,.43-0.06A0.4,0.4,0,0,1,13.39,3.29Z" fill="#26d9bb" stroke="#22b296" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
Before Width: | Height: | Size: 474 B After Width: | Height: | Size: 499 B |
Loading…
Reference in a new issue