ASWA Examples v2.0 (#55)
* swa examples v2.0 * update to main README.md file * update to PR guidelines and checklist * removed docs and existing content * removed deploy and test-deploy workflows
|
@ -6,49 +6,35 @@
|
|||
|
||||
1. Fork the repository
|
||||
1. Create a branch for your addition **(for instance, {account}-sunrise-standup)**
|
||||
1. Include a screenshot of your app in the `./media/` folder
|
||||
1. Identify the correct table for your example
|
||||
1. Include the app information (use the following code snippet as a template):
|
||||
|
||||
```md
|
||||
### [My Cool App](https://example.com)
|
||||
|
||||
<p align="center">
|
||||
<img src="./media/your-app.png" alt="My Cool App" width="100%">
|
||||
</p>
|
||||
|
||||
<a short description of the app>
|
||||
|
||||
- Link to the project: **[HERE](https://example.com)**
|
||||
- GitHub repo: **[HERE](https://github.com/microsoft)**
|
||||
|
||||
> Stacks Used: `gatsby, nodejs, azure static web apps`
|
||||
> Author Twitter (optional): [@name](https://twitter.com/@name)
|
||||
## Azure Static Web Apps + [Technology/ Language]
|
||||
|
||||
| # | Demo | Description |
|
||||
|---| -------------------- | ----------- |
|
||||
| 1 | [My Cool App](https://github.com/<your-repo-here>) |<a short description of the app> <br> <img src="media/icons/<select-stack-icon>" alt="<product/stack name>" width="19" height="18" /> <br> [Try Live](https://example.com) |
|
||||
```
|
||||
|
||||
### Add a new technology (optional)
|
||||
|
||||
If you are including a new technology not listed in the README, please follow these steps:
|
||||
|
||||
1. Under the **Projects** section, update the table of content and include the new technology.
|
||||
1. **Make you respect the alphabetical order**
|
||||
1. Add your application name as a sub-list.
|
||||
1. **Make sure you use the same acnhors that point to the app information (see above)**
|
||||
1. On the **Navbar** at the top, update the list with the respective badge from https://img.shields.io/.
|
||||
1. **Make you respect the order**
|
||||
1. Add the new section with a short description and table (See above)
|
||||
1. Upload and link to any new icons in **media/icons**
|
||||
|
||||
```md
|
||||
- [Gatsby](#gatsby)
|
||||
- [Gatsby Todo App](#gatsby-todo-app)
|
||||
```
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] update table of content
|
||||
- [ ] add media file to `./media/`
|
||||
- [ ] update navbar
|
||||
- [ ] add icons to `./media/icons`
|
||||
- [ ] add app name and link
|
||||
- [ ] add app description
|
||||
- [ ] add used tech stack
|
||||
- [ ] add URL to app to the app on Azure Static Web Apps
|
||||
- [ ] add URL to app repository
|
||||
- [ ] add author twitter handle (optional)
|
||||
|
||||
❤️ Thank you for your contributions!
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
name: Deploy to GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
# Review gh actions docs if you want to further define triggers, paths, etc
|
||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on
|
||||
paths: [www/**]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy to GitHub Pages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
cache: npm
|
||||
- name: Build website
|
||||
working-directory: www
|
||||
run: |
|
||||
npm ci
|
||||
npm run build
|
||||
|
||||
# Popular action to deploy to GitHub Pages:
|
||||
# Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# Build output to publish to the `gh-pages` branch:
|
||||
publish_dir: ./build
|
||||
# The following lines assign commit authorship to the official
|
||||
# GH-Actions bot for deploys to `gh-pages` branch:
|
||||
# https://github.com/actions/checkout/issues/13#issuecomment-724415212
|
||||
# The GH actions bot is used by default if you didn't specify the two fields.
|
||||
# You can swap them out with your own user credentials.
|
||||
user_name: github-actions[bot]
|
||||
user_email: 41898282+github-actions[bot]@users.noreply.github.com
|
|
@ -1,26 +0,0 @@
|
|||
name: Test deployment
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
# Review gh actions docs if you want to further define triggers, paths, etc
|
||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on
|
||||
paths: [www/**]
|
||||
|
||||
jobs:
|
||||
test-deploy:
|
||||
name: Test deployment
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
cache: yarn
|
||||
|
||||
- name: Test build
|
||||
working-directory: www
|
||||
run: |
|
||||
npm ci
|
||||
npm run build
|
363
README.md
|
@ -1,262 +1,127 @@
|
|||
# Azure Static Web Apps Gallery
|
||||
<div align="center">
|
||||
<h1>🌐Static Web Apps Examples</h1>
|
||||
|
||||
Welcome to the Azure Static Web Apps Gallery - a showcase of awesome projects built by community, and deployed to the **[Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/?WT.mc_id=staticwebapps-github-cxa)** service.
|
||||
|
||||
---
|
||||
|
||||
## 🔥 | Add Your Project
|
||||
|
||||
Want to have your project listed in the gallery?
|
||||
* Review the [**Contributing Guidelines**](CONTRIBUTING.md).
|
||||
* Fork [**the repository**](https://github.com/microsoft/static-web-apps-gallery-code-samples/fork) and create a branch for your addition
|
||||
* Follow this **[Pull Request Checklist](./.github/PULL_REQUEST_TEMPLATE/pull_request_template.md)**.
|
||||
|
||||
---
|
||||
|
||||
## 📝 | Technologies Showcased
|
||||
|
||||
The table showcases technologies for which projects were added - click the technology to visit the _section_ showcasing all its projects. If a project has a demo URL, the _IsLive_ column shows if that is still active (last-checked: **`Apr 18, 2022`**)
|
||||
|
||||
| Technology | Project | Is Live |
|
||||
|:---|:---|:---|
|
||||
| [`Angular`](#Angular) | [Catsify: A cat names generator](#catsify-a-cat-names-generator)| ✅ |
|
||||
| | [ngxtools: Angular Package Registry](#ngxtools-angular-package-registry)| ✅ |
|
||||
| | [angular-swa-auth library demo](#angular-swa-auth-library-demo)| ✅ |
|
||||
| [`Docusaurus`](#docusaurus)| [Docusaurus Starter](#docusaurus-starter)| ✅ |
|
||||
| [`Hugo`](#hugo) | [ngVikings 2020 Conference](#ngvikings-2020-a-free-online-conference-for-angular-developers)| ✅ |
|
||||
| [`Scully`](#scully)| [PWA Blog](#pwa-blog)| ✅ |
|
||||
| [`Svelte`](#svelte)| [Shop at Home](#shop-at-home)|✅|
|
||||
| [`Vanilla HTML/JS/CSS`](#vanilla-html-javascript-css)|[SWAG Demo: A Positive Thought For Your Day](#azure-swag-demo-a-positive-thought-for-your-day) | ✅ |
|
||||
| |[Nitrooo landing page](#nitrooo-landing-page) | ✅ |
|
||||
| |[Hexa CLI Landing Page](#hexa-cli-landing-page) | ✅ |
|
||||
| |[VS Code Can Do That](#vs-code-can-do-that) | ✅ |
|
||||
|[`VuePress`](#vuepress) | [Nitro Workshop](#nitro-workshop)| ✅ |
|
||||
| | [Peacock for Visual Studio Code Documentation](#peacock-for-visual-studio-code-documentation)| ✅ |
|
||||
| |[Cognitive Search Static Apps Demo](#cognitive-search-static-apps-demo) | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 💻 | Projects (By Technology)
|
||||
|
||||
## Angular
|
||||
|
||||
### **[Catsify: A cat names generator](https://www.catsify.app/)**
|
||||
[<img src="media/icons/ai-studio.svg" alt="OpenAI" width="24" height="24" /> ](#azure-static-web-apps--ai)
|
||||
<span> • </span>
|
||||
[![React](https://img.shields.io/badge/React-20232A?style=for-the-badge&logo=react&logoColor=61DAFB)](#azure-static-web-apps--web-frameworks)
|
||||
<span> • </span>
|
||||
[![Svelte](https://img.shields.io/badge/Svelte-4A4A55?style=for-the-badge&logo=svelte&logoColor=FF3E00)](#azure-static-web-apps--web-frameworks)
|
||||
<span> • </span>
|
||||
[![Vue.js](https://img.shields.io/badge/Vue.js-35495E?style=for-the-badge&logo=vue.js&logoColor=4FC08D)](#azure-static-web-apps--web-frameworks)
|
||||
<span> • </span>
|
||||
[![Angular](https://img.shields.io/badge/Angular-DD0031?style=for-the-badge&logo=angular&logoColor=white)](#azure-static-web-apps--web-frameworks)
|
||||
<span> • </span>
|
||||
[![JavaScript](https://img.shields.io/badge/JavaScript-F7DF1E?style=for-the-badge&logo=javascript&logoColor=black)](#azure-static-web-apps-with-javascriptnodejs)
|
||||
<span> • </span>
|
||||
[![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white)](#azure-static-web-apps-with-typescriptnodejs)
|
||||
<span> • </span>
|
||||
[![Node.js](https://img.shields.io/badge/Node.js-43853D?style=for-the-badge&logo=node.js&logoColor=white)](#azure-static-web-apps-with-javascriptnodejs)
|
||||
<span> • </span>
|
||||
[![.NET](https://img.shields.io/badge/.NET-5C2D91?style=for-the-badge&logo=.net&logoColor=white)](#azure-static-web-apps-with-net-and-blazor)
|
||||
<span> • </span>
|
||||
[![Python](https://img.shields.io/badge/Python-3776AB?style=for-the-badge&logo=python&logoColor=white)](#azure-static-web-apps-with-python)
|
||||
<span> • </span>
|
||||
[![Java](https://img.shields.io/badge/Java-ED8B00?style=for-the-badge&logo=openjdk&logoColor=white)](#azure-static-web-apps-with-java)
|
||||
<span> • </span>
|
||||
[![Go](https://img.shields.io/badge/Go-00ADD8?style=for-the-badge&logo=go&logoColor=white)](#azure-static-web-apps-with-go)
|
||||
</div>
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/media/catsify.png" alt="Catsify App" width="100%">
|
||||
<img src="media/images/appservicestatic.jpg" alt="Azure Static Web Apps" />
|
||||
</p>
|
||||
|
||||
Catsify is a simple and creative app that allows you to find a unique name for your lovely cat. What's interesting about this app is that the names generator is all written in Rust and compiled to WASM; and the API is exposed through a Node.js Azure Function.
|
||||
This repository showcases a variety of examples, tutorials, and use cases of applications developed using different programming languages and frameworks, all hosted on **[Azure Static Web Apps](https://learn.microsoft.com/azure/static-web-apps/?WT.mc_id=javascript-154160-juliamuiruri)**.
|
||||
|
||||
- Link to the project: **[HERE](https://www.catsify.app/)**
|
||||
- GitHub repo: **[HERE](https://github.com/manekinekko/catsify)**
|
||||
If you have a real-world application in production and would like to share it, we invite you to contribute by opening an issue and then a pull request. If you would like to view examples at the production level, please refer to the designated section: [Real World and Production examples with Azure Static Web Apps](#real-world-and-production-examples-com-azure-static-web-apps).
|
||||
|
||||
> Stacks Used: `angular, typescript, azure static web apps, rust, web assembly, nodejs, azure functions`
|
||||
> [!NOTE]
|
||||
> Missing an application or specific example? Provide us with your feedback by opening an Issue and suggesting the inclusion of new examples.
|
||||
|
||||
---
|
||||
## Azure Static Web Apps + AI
|
||||
|
||||
## Docusaurus
|
||||
Here you will find examples of intelligent (AI-Powered) applications running on Azure Static Web Apps, showcasing the diversity of scenarios and best practices for adopting AI integration in real-world projects.
|
||||
|
||||
### **[Docusaurus Starter](https://ambitious-pebble-02b2d3010.azurestaticapps.net/)**
|
||||
| # | Demo | Description |
|
||||
|---| -------------------- | ----------- |
|
||||
| 1 | [session-recommender](https://github.com/Azure-Samples/azure-sql-db-session-recommender-v2) | A session recommender for your next event. <br> <img src="media/icons/openai-logomark.png" alt="OpenAI" width="18" /> <img src="media/icons/AzureFunctionsApp.svg" alt="Azure Functions" width="19" height="18" /> <img src="media/icons/SQL.svg" alt="Azure SQL" width="18" height="18" /> <img src="media/icons/dab-logo.png" alt="Data API Builder" width="18" height="19" /> <br>[Try Live](https://ai.microsofthq.vslive.com/) |
|
||||
| 2 | [create-your-own-chatgpt](https://github.com/Azure-Samples/azure-openai-rag-workshop) | An AI-powered chat application with RAG. <br> <img src="media/icons/aoi.svg" alt="Azure OpenAI" width="15" height="19" /> <img src="media/icons/nodejs.png" alt="Nodejs" width="16" height="18" /> <img src="media/icons/fastify-logo.png" alt="Fastify" width="23" /> <img src="media/icons/langchainjs.png" alt="Langchain.js" width="29" /> |
|
||||
| 3 | [serverless-ai-chat](https://github.com/Azure-Samples/serverless-chat-langchainjs) | A Serverless AI Chat application. <br> <img src="media/icons/ollama.png" alt="Ollama" height="17" /> <img src="media/icons/AzureFunctionsApp.svg" alt="Azure Functions" width="18" height="18" /> <img src="media/icons/cosmos.svg" alt="Azure CosmosDB" width="18" height="18" /> <img src="media/icons/langchainjs.png" alt="Langchain.js" width="23" /> |
|
||||
| 4 | [crafting-dynamic-document-models-DI](https://github.com/Azure-Samples/azure-doc-intelligence-dynamic-models-patient) | Solution to improve the patient experience by automating the paper based registration process. <br> <img src="media/icons/cosmos.svg" alt="Azure CosmosDB" width="18" height="18" /> <img src="media/icons/document-intelligence.svg" alt="Azure Document Intelligence" width="15" height="15" /> |
|
||||
| 5 | [podcast-synopsis-generation](https://github.com/Azure-Samples/podcast-synopsis-generation-openai) | A Pipeline For Podcast Synopsis Generation (and more) With Azure OpenAI. <br> <img src="media/icons/openai-logomark.png" alt="OpenAI" width="16" /> <img src="media/icons/AzureFunctionsApp.svg" alt="Azure Functions" width="18" height="18" /> <img src="media/icons/cognitive-services.svg" alt="Azure Cognitive services" width="18" height="18" /> |
|
||||
| 6 | [openai-assistant-function-calling](https://github.com/Azure-Samples/azure-openai-assistant-javascript) | Serverless Azure OpenAI Assistant Quick Start Function Calling. <br> <img src="media/icons/AzureFunctionsApp.svg" alt="Azure Functions" width="18" height="18" /> <img src="media/icons/aoi.svg" alt="Azure OpenAI" width="16" height="16" /> |
|
||||
|
||||
## Azure Static Web Apps + Web Frameworks
|
||||
|
||||
Here you will find examples of applications built using a variety of Frameworks running on Azure Static Web Apps.
|
||||
|
||||
| # | Demo | Description |
|
||||
|---| -------------------- | ----------- |
|
||||
| 1 | [**svelte**-shop-at-home](https://github.com/azure-template-resources/shopathome-svelte) | Shop at Home app that allows customers to securely add, edit, view, and remove items such as food and household needs from their list. <br> <img src="media/icons/AzureFunctionsApp.svg" alt="Azure Functions" width="19" height="18" /> <img src="media/icons/fastify-logo.png" alt="Fastify" width="23" /> <br> [Try Live](https://svelte.shopathome.dev/home) |
|
||||
| 2 | [**angular**-shop-at-home](https://github.com/azure-template-resources/shopathome-svelte) | Shop at Home app that allows customers to securely add, edit, view, and remove items such as food and household needs from their list. <br> <img src="media/icons/AzureFunctionsApp.svg" alt="Azure Functions" width="19" height="18" /> <img src="media/icons/fastify-logo.png" alt="Fastify" width="23" /> <br> [Try Live](https://angular.shopathome.dev/home) |
|
||||
| 3 | [**react**-shop-at-home](https://github.com/azure-template-resources/shopathome-react) | Shop at Home app that allows customers to securely add, edit, view, and remove items such as food and household needs from their list. <br> <img src="media/icons/AzureFunctionsApp.svg" alt="Azure Functions" width="19" height="18" /> <img src="media/icons/fastify-logo.png" alt="Fastify" width="23" /> <br> [Try Live](https://react.shopathome.dev/home) |
|
||||
| 4 | [**vue**-shop-at-home](https://github.com/azure-template-resources/shopathome-vue) | Shop at Home app that allows customers to securely add, edit, view, and remove items such as food and household needs from their list. <br> <img src="media/icons/AzureFunctionsApp.svg" alt="Azure Functions" width="19" height="18" /> <img src="media/icons/fastify-logo.png" alt="Fastify" width="23" /> <br> [Try Live](https://react.shopathome.dev/home) |
|
||||
| 5 | [**vue.js**-fullstack-todo-list](https://github.com/Azure-Samples/azure-sql-db-fullstack-serverless-kickstart) | A todo e2e reference app <br> <img src="media/icons/AzureFunctionsApp.svg" alt="Azure Functions" width="19" height="18" /> <img src="media/icons/SQL.svg" alt="Azure SQL" width="18" height="18" /> |
|
||||
| 6 | [**React**-3Tier-todo-app](https://github.com/azure-template-resources/todo-nodejs-pgsql-googleAuth) | A sample Todo app to help you learn how to build a full-stack application with authentication and authorization <br> <img src="media/icons/nodejs.png" alt="Nodejs" width="16" height="18" /> <img src="media/icons/postgresql.svg" alt="PostgreSQL DB" width="16" height="18" /> <img src="media/icons/google-auth.png" alt="Google Authentication" width="16" height="18" /> |
|
||||
|
||||
|
||||
## Azure Static Web Apps with JavaScript/Node.js
|
||||
|
||||
The following examples demonstrate how to create applications using JavaScript and Node.js, hosted on Azure Static Web Apps.
|
||||
|
||||
| # | Demo | Description |
|
||||
|---| -------------------- | ----------- |
|
||||
| 1 | [nodejs-microservices](https://github.com/Azure-Samples/nodejs-microservices) | A sample application showing Node.js microservices usage with an Azure infrastructure. <br> <img src="media/icons/icons8-vite.svg" alt="Vite" width="18" height="18" /> <img src="media/icons/nodejs.png" alt="Nodejs" width="16" height="18" /> <img src="media/icons/nestjs.png" alt="Nestjs" width="16" height="18" /> <img src="media/icons/fastify-logo.png" alt="Fastify" width="23" /> |
|
||||
|
||||
|
||||
## Azure Static Web Apps with TypeScript/Node.js
|
||||
|
||||
The following examples demonstrate how to create applications using TypeScript and Node.js, hosted on Azure Static Web Apps.
|
||||
|
||||
| # | Demo | Description |
|
||||
|---| -------------------- | ----------- |
|
||||
| 1 | [rest-graphql-todoMVC](https://github.com/Azure-Samples/azure-sql-db-prisma) | REST & GraphQL TodoMVC Sample App Full Stack Implementation with Prisma. <br> <img src="media/icons/AzureFunctionsApp.svg" alt="Azure Functions" width="19" height="18" /> <img src="media/icons/SQL.svg" alt="Azure SQL" width="18" height="18" /> <img src="media/icons/vuejs.png" alt="Vuejs" width="18" height="18" /> <img src="media/icons/prisma.webp" alt="Prisma" width="18" height="18" /> <img src="media/icons/github-actions.png" alt="GitHub Actions" width="18" height="18" /> |
|
||||
|
||||
## Azure Static Web Apps with .NET and Blazor
|
||||
|
||||
The following examples demonstrate how to create applications using .NET and Blazor, hosted on Azure Static Web Apps.
|
||||
|
||||
| # | Demo | Description |
|
||||
|---| -------------------- | ----------- |
|
||||
| 1 | [products-finder](https://github.com/Azure-Samples/dab-azure-cosmos-db-nosql-quickstart) | A products finder implemented using Data API Builder. <br> <img src="media/icons/Blazor.png" alt="Blazor" width="16" height="18" /> <img src="media/icons/AzureFunctionsApp.svg" alt="Azure Functions" width="19" height="18" /> <img src="media/icons/cosmos.svg" alt="Azure CosmosDB" width="18" height="18" /> <img src="media/icons/dab-logo.png" alt="Data API Builder" width="18" height="19" /> |
|
||||
|
||||
## Azure Static Web Apps with Python
|
||||
|
||||
The following examples demonstrate how to create applications using Python, hosted on Azure Static Web Apps.
|
||||
|
||||
| # | Demo | Description |
|
||||
|---| -------------------- | ----------- |
|
||||
| 1 | [todo-application](https://github.com/Azure-Samples/todo-python-mongo-swa-func) | A TODO blueprint placeholder frontend <br> <img src="media/icons/cosmos.svg" alt="Azure CosmosDB" width="18" height="18" /> <img src="media/icons/fastapi.svg" alt="FastAPI" width="18" height="18" /> |
|
||||
|
||||
|
||||
# Real World and Production Examples with Azure Static Web Apps
|
||||
|
||||
Here you will find examples of applications in production using Azure Static Web Apps, showcasing the diversity of scenarios and best practices for adopting this service in real-world projects.
|
||||
|
||||
| # | Demo | Description |
|
||||
|---| -------------------- | ----------- |
|
||||
| 1 | [ngVikings 2020](https://github.com/ngvikings/ngvikings-2020) <br> <img src="media/icons/hugo-icon.png" alt="Hugo" width="38" /> | Website for ngVikings conference. ngVikings is a non-profit, non-commercial, 100% community-driven event comprised of many Nordic Angular groups with more than 6500 active members in total. <br> [Try Live](https://www.ngvikings.org/) |
|
||||
| 2 | [Nitro Workshop](https://github.com/nitro-stack/nitro-workshop) <br> <img src="media/icons/nodejs.png" alt="Nodejs" width="16" height="18" /> <img src="media/icons/vuepress.png" alt="Vuepress" width="22" /> <img src="media/icons/nestjs.png" alt="Nestjs" width="16" height="18" /> | Online workshop built with Vuepress to learn how to build a backend using NestJS. This is a practical workshop where you'll learn "hands-on" by iteratively building an application from scratch using NestJS and Azure. <br> [Try Live](https://nitro-stack.github.io/nitro-workshop/) |
|
||||
| 3 | [Peacock for Visual Studio Code Documentation](https://github.com/johnpapa/vscode-peacock) <br> <img src="media/icons/nodejs.png" alt="Nodejs" width="16" height="18" /> <img src="media/icons/vuepress.png" alt="Vuepress" width="22" /> | Peacock is a Visual Studio Code extension with 700,000+ installations. It subtly changes the color of your Visual Studio Code workspace. This is ideal when you have multiple VS Code instances, use VS Live Share, or use VS Code's Remote features, and you want to quickly identify your editor. <br> [Try Live](https://www.peacockcode.dev/) |
|
||||
|
||||
# 🤝 Contributing
|
||||
|
||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
||||
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
|
||||
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
|
||||
|
||||
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
|
||||
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
|
||||
provided by the bot. You will only need to do this once across all repos using our CLA.
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
|
||||
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/media/docusaurus-starter.PNG" alt="Docusaurus starter" width="100%">
|
||||
🚀 <strong>Get started now and take your app to the next level with <a href="https://learn.microsoft.com/azure/static-web-apps/?WT.mc_id=javascript-154160-juliamuiruri">Azure Static Web Apps</a>!</strong>
|
||||
</p>
|
||||
|
||||
A simple starter template for creating documentation website using the Docusaurus framework.
|
||||
|
||||
> Stacks Used: `reactjs, azure static web apps`
|
||||
|
||||
- Link to the project: **[HERE](https://ambitious-pebble-02b2d3010.azurestaticapps.net/)**
|
||||
- GitHub repo: **[HERE](https://github.com/sumitkharche/docusaurus-swa-app)**
|
||||
- Author: [@sumitkharche01](https://twitter.com/sumitkharche01)
|
||||
|
||||
---
|
||||
|
||||
## Gatsby
|
||||
|
||||
---
|
||||
|
||||
## Hugo
|
||||
|
||||
### **[ngVikings 2020: A free online conference for Angular developers](https://www.ngvikings.org/)**
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/media/ngvikings2020.png" alt="ngVikings 2020" width="100%">
|
||||
</p>
|
||||
|
||||
ngVikings is a non-profit, non-commercial, 100% community-driven event comprised of many Nordic Angular groups with more than 6500 active members in total.
|
||||
|
||||
- **[ngVikings site](https://www.ngvikings.org/)**
|
||||
- **[ngVikings repo](https://github.com/ngvikings/ngvikings-2020)**
|
||||
|
||||
> Stacks Used: `hugo, azure static web apps, workbox`
|
||||
|
||||
---
|
||||
|
||||
## Mongoose
|
||||
|
||||
![Mongoose logo](docs/media/mongoose.png)
|
||||
|
||||
### [Azure Static Web Apps and Mongoose Starter Kit](https://github.com/GeekTrainer/aswa-student-starter-kit)
|
||||
|
||||
![Preview image for Mongoose starter kit](docs/media/mongoose-starter.png)
|
||||
|
||||
Mongoose is the most popular ODM (object document mapper) for Node.js. This basic starter includes the necessary code and steps to create Azure Static Web Apps with Cosmos DB and Mongoose. No front-end framework is used, allowing you to update the site as needed.
|
||||
|
||||
> Stacks Used: `mongoose, cosmos db, azure static web apps`
|
||||
|
||||
- **[Mongoose Starter Kit repo](https://github.com/geektrainer/aswa-student-starter-kit)
|
||||
- **[Author: GeekTrainer](https://twitter.com/geektrainer)
|
||||
|
||||
---
|
||||
|
||||
## React.js
|
||||
|
||||
---
|
||||
|
||||
### **[PWA Blog](https://www.webmax.ru/)**
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/media/pwablog.png" alt="PWA Blog" width="100%">
|
||||
</p>
|
||||
|
||||
News and articles about Progressive Web Apps.
|
||||
|
||||
- **[Progressive web apps information](https://www.webmax.ru/)**
|
||||
- **[Progressive web apps repo](https://github.com/webmaxru/webmax.ru)**
|
||||
|
||||
> Stacks Used: `angular, scully, azure static web apps, workbox, pwa`
|
||||
|
||||
---
|
||||
|
||||
## Svelte
|
||||
|
||||
### **[Shop at Home](https://www.shopathome.dev)**
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/media/shop-at-home-svelte.png" alt="Svelte Application" width="100%">
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
"Shop at Home" is a sample app which is written in four variations: Angular, React, Svelte and Vue. It is shown in the Build 2020 video presentation.
|
||||
|
||||
- **[Shop at Home demo](https://www.shopathome.dev)**
|
||||
- **[Shop at Home repo](https://github.com/johnpapa/shopathome)**
|
||||
|
||||
> Stacks Used: `svelte, react, angular, nodejs, azure static web apps`
|
||||
|
||||
---
|
||||
|
||||
## Vanilla HTML JavaScript CSS
|
||||
|
||||
### **[Azure SWAG Demo: A Positive Thought For Your Day](https://ashy-mushroom-05748f31e.azurestaticapps.net/)**
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/media/positive-quote.png" alt="Positive quote website screenshot" width="100%">
|
||||
</p>
|
||||
|
||||
This is a simple barebone demo for [Azure SWAG](https://docs.microsoft.com/azure/static-web-apps?WT.mc_id=staticwebapps-github-yolasors) (**S**tatic **W**eb **A**pps on **G**itHub).
|
||||
You can use it as a template for your own apps.
|
||||
|
||||
- **[SWAG demo](https://aka.ms/swag-demo)**
|
||||
- **[SWAG repo](https://github.com/sinedied/azure-swag/)**
|
||||
|
||||
> Stacks Used: `html, javascript, nodejs, azure static web apps`
|
||||
|
||||
---
|
||||
|
||||
### **[Nitrooo landing page](https://victorious-ocean-0337ef81e.azurestaticapps.net/)**
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/media/nitrooo.png" alt="Nitrooo App" width="100%">
|
||||
</p>
|
||||
|
||||
Nitro is a heavily opinionated template for building Serverless applications with NestJS, the fastest-growing NodeJS framework in the world by github stars.
|
||||
|
||||
- **[Nitrooo project](https://victorious-ocean-0337ef81e.azurestaticapps.net/)**
|
||||
- **[Nitrooo repo](https://github.com/nitro-stack/website)**
|
||||
|
||||
> Stacks Used: `javascript, css, html`
|
||||
|
||||
---
|
||||
|
||||
### **[Hexa CLI Landing Page](https://www.hexa.run)**
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/media/hexa.png" alt="The ultimate companion for the Azure CLI screenshot" width="100%">
|
||||
</p>
|
||||
|
||||
Hexa is the ultimate companion for the Azure CLI. It allows you to seamlessly configure, setup and deploy to different Azure services such as Resource Groups, Storage accounts, Hosting, Azure Functions and Databases (CosmosDB and Table Storage) and more.
|
||||
|
||||
- **[Hexa project](https://www.hexa.run)**
|
||||
- **[Hexa repo](https://github.com/manekinekko/hexa/)**
|
||||
|
||||
> Stacks Used: `html, css, javascript`
|
||||
|
||||
---
|
||||
|
||||
## Vue.js
|
||||
|
||||
### **[VS Code Can Do That](https://www.vscodecandothat.com)**
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/media/vscodecandothat.png" alt="Vs Code Can Do That" width="100%">
|
||||
</p>
|
||||
|
||||
All the best things about VS Code that nobody ever bothered to show you.
|
||||
|
||||
- **[VS Code Can Do That demo](https://www.vscodecandothat.com)**
|
||||
- **[VS Code Can Do That repo](https://github.com/burkeholland/vscodecandothat/)**
|
||||
|
||||
> Stacks Used: `vuejs, azure static web apps`
|
||||
|
||||
---
|
||||
|
||||
## VuePress
|
||||
|
||||
### **[Nitro Workshop](https://nitro-stack.github.io/nitro-workshop/)**
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/media/nitro.png" alt="Nitro logo" width="256" height="256">
|
||||
<p>
|
||||
|
||||
Online workshop built with Vuepress to learn how to build a backend using NestJS. This is a practical workshop where you'll learn "hands-on" by iteratively building an application from scratch using NestJS and Azure.
|
||||
|
||||
- **[Nitro workshop](https://nitro-stack.github.io/nitro-workshop/)**
|
||||
- **[Nitro workshop repo](https://github.com/nitro-stack/nitro-workshop)**
|
||||
|
||||
> Stacks Used: `vuepress, azure static web apps, nodejs, nestjs`
|
||||
|
||||
---
|
||||
|
||||
### **[Peacock for Visual Studio Code Documentation](https://www.peacockcode.dev)**
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/media/peacock-icon.png" alt="Peacock icon" width="256" height="256">
|
||||
<p>
|
||||
|
||||
Peacock is a Visual Studio Code extension with 700,000+ installations. It subtly changes the color of your Visual Studio Code workspace. This is ideal when you have multiple VS Code instances, use VS Live Share, or use VS Code's Remote features, and you want to quickly identify your editor.
|
||||
|
||||
- **[Peacock Documentation](https://www.peacockcode.dev)**
|
||||
- **[GitHub repo for Peacock Documentation](https://github.com/johnpapa/vscode-peacock)**
|
||||
- **[Install the Peacock Extension](https://marketplace.visualstudio.com/items?itemName=johnpapa.vscode-peacock&wt.mc_id=staticwebapps-github-jopapa)**
|
||||
|
||||
> Stacks Used: `vuepress, azure static web apps, nodejs`
|
||||
|
||||
---
|
||||
|
||||
### [Cognitive Search Static Apps Demo](https://lively-sand-033e9ec03.azurestaticapps.net/)
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/media/cognitive-search-demo.png" alt="Cognitive Search Static Apps Demo" width="100%">
|
||||
</p>
|
||||
|
||||
A sample *faceted search* user experience implementation for your [Azure Cognitive Search](https://azure.microsoft.com/services/search/) index. Similar to the [official demo app](https://docs.microsoft.com/azure/search/search-create-app-portal), but a bit more modern. Fork the [repo](https://github.com/scale-tone/cognitive-search-static-web-apps-sample-ui), [deploy](https://docs.microsoft.com/azure/static-web-apps/getting-started?tabs=react#create-a-static-web-app) it to your Static Web Apps instance, connect it to your Cognitive Search index with a set of [config settings](https://github.com/scale-tone/cognitive-search-static-web-apps-sample-ui#config-settings), optionally [configure authN/authZ](https://docs.microsoft.com/azure/static-web-apps/authentication-authorization) - and you get a fully functioning search UI, with facet filters and geovisualization. The [live demo](https://lively-sand-033e9ec03.azurestaticapps.net/) is pointed to [the official Azure Cognitive Search Sample Data - Repository](https://github.com/Azure-Samples/azure-search-sample-data) index, and you can start with the same. Feel free to use as a template for your own implementations.
|
||||
|
||||
- **[Lively Sand demo](https://lively-sand-033e9ec03.azurestaticapps.net/)**
|
||||
- **[Lively Sand repo](https://github.com/scale-tone/cognitive-search-static-web-apps-sample-ui)**
|
||||
- **[Author: @tino_scale_tone](https://twitter.com/@tino_scale_tone)**
|
||||
|
||||
> Stacks Used: `react, nodejs, azure static web apps, azure functions`
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
# 💻 | Projects (By Technology)
|
||||
|
||||
Welcome to the Azure Static Web Apps Gallery - a showcase of awesome projects built by community, and deployed to the **[Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/?WT.mc_id=staticwebapps-github-cxa)** service. Click on a technology name to visit the section showcasing its projects.
|
||||
|
||||
* [Angular](#angular)
|
||||
* [Docusaurus](#docusaurus)
|
||||
* [Eleventy](#eleventy)
|
||||
* [Gatsby](#gatsby)
|
||||
* [Hugo](#hugo)
|
||||
* [Mongoose](#mongoose)
|
||||
* [React](#reactjs)
|
||||
* [Stencil](#stencil)
|
||||
* [Scully](#scully)
|
||||
* [Svelte](#svelte)
|
||||
* [Vanilla HTML/JS/CSS](#vanilla-html-javascript-css)
|
||||
* [Vue.js](#vuejs)
|
||||
* [VuePress](#vuepress)
|
||||
|
||||
> Work in Progress
|
Двоичные данные
docs/media/11ty.png
До Ширина: | Высота: | Размер: 491 KiB |
Двоичные данные
docs/media/angular-rock-paper-scissors.png
До Ширина: | Высота: | Размер: 141 KiB |
Двоичные данные
docs/media/angular-search-experience.gif
До Ширина: | Высота: | Размер: 4.1 MiB |
Двоичные данные
docs/media/angular-ssr.png
До Ширина: | Высота: | Размер: 225 KiB |
Двоичные данные
docs/media/angular-swa-auth.gif
До Ширина: | Высота: | Размер: 2.0 MiB |
Двоичные данные
docs/media/azure_vision.gif
До Ширина: | Высота: | Размер: 4.9 MiB |
Двоичные данные
docs/media/catsify.png
До Ширина: | Высота: | Размер: 430 KiB |
Двоичные данные
docs/media/cognitive-search-demo.png
До Ширина: | Высота: | Размер: 603 KiB |
Двоичные данные
docs/media/docusaurus-starter.PNG
До Ширина: | Высота: | Размер: 36 KiB |
Двоичные данные
docs/media/gatsby_starter.png
До Ширина: | Высота: | Размер: 53 KiB |
Двоичные данные
docs/media/hexa.png
До Ширина: | Высота: | Размер: 826 KiB |
Двоичные данные
docs/media/mayadb.png
До Ширина: | Высота: | Размер: 280 KiB |
Двоичные данные
docs/media/meme4fun.gif
До Ширина: | Высота: | Размер: 2.4 MiB |
Двоичные данные
docs/media/mongoose-starter.png
До Ширина: | Высота: | Размер: 11 KiB |
Двоичные данные
docs/media/mongoose.png
До Ширина: | Высота: | Размер: 48 KiB |
Двоичные данные
docs/media/ngvikings2020.png
До Ширина: | Высота: | Размер: 616 KiB |
Двоичные данные
docs/media/ngxtools.png
До Ширина: | Высота: | Размер: 1.0 MiB |
Двоичные данные
docs/media/nitro.png
До Ширина: | Высота: | Размер: 34 KiB |
Двоичные данные
docs/media/nitrooo.png
До Ширина: | Высота: | Размер: 62 KiB |
Двоичные данные
docs/media/peacock-icon.png
До Ширина: | Высота: | Размер: 14 KiB |
Двоичные данные
docs/media/posedance.png
До Ширина: | Высота: | Размер: 786 KiB |
Двоичные данные
docs/media/positive-quote.png
До Ширина: | Высота: | Размер: 3.1 MiB |
Двоичные данные
docs/media/pwablog.png
До Ширина: | Высота: | Размер: 578 KiB |
Двоичные данные
docs/media/shop-at-home-svelte.png
До Ширина: | Высота: | Размер: 51 KiB |
Двоичные данные
docs/media/stencil.png
До Ширина: | Высота: | Размер: 185 KiB |
Двоичные данные
docs/media/sunrise-standup.png
До Ширина: | Высота: | Размер: 249 KiB |
Двоичные данные
docs/media/vscodecandothat.png
До Ширина: | Высота: | Размер: 438 KiB |
Двоичные данные
docs/media/xlayers-1.png
До Ширина: | Высота: | Размер: 1.4 MiB |
Двоичные данные
docs/media/xlayers-2.png
До Ширина: | Высота: | Размер: 1.4 MiB |
|
@ -1,20 +0,0 @@
|
|||
# Dependencies
|
||||
/node_modules
|
||||
|
||||
# Production
|
||||
/build
|
||||
|
||||
# Generated files
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
|
@ -1,54 +0,0 @@
|
|||
# Build & Deploy This Site
|
||||
|
||||
This website was built using [Docusaurus 2](https://docusaurus.io/) using their default `classic` theme. It will primarily host a [Showcase](https://docusaurus.io/showcase)-like page to display screenshots of submitted projects with ability to filter by technology-specific tags.
|
||||
|
||||
---
|
||||
|
||||
## 0. Updating Content for Existing Site
|
||||
|
||||
Want to update the existing site to add new content (logos, screenshots, cards etc.)? Here are the key files to know.
|
||||
|
||||
| Filename | Description |
|
||||
|:--- |:--- |
|
||||
| [`static/img/logo-XXX.svg`](./static/img/) | Add valid logo images for frameworks used on landing page here. Ideally in SVG format. |
|
||||
| [`src/components/HomepageFeatures/index.js`](./src/components/HomepageFeatures/index.js) | Update this file when adding content to landing page (e.g., new front-end framework logos)|
|
||||
| [`src/data/showcase/`](./src/data/showcase/) | Folder containing (user-uploaded) screenshots for showcase cards. |
|
||||
| `src/data/showcase/tags.tsx` | File containing tags (and definitions) valid for filtering showcase. Admin-maintained but could be user-contributed later? |
|
||||
| `src/data/showcase/users.tsx` | File containing user-contributed project metadata. Maintain in alphabetical order, ensure valid tags & screenshot are provided. |
|
||||
| | |
|
||||
|
||||
Want to know how the site is configured, built and deployed? Read on.
|
||||
|
||||
<br/>
|
||||
|
||||
## 1. Setup & Build Commands
|
||||
|
||||
The default site is scaffolded in the `www/` folder under `docs` with the intent of using GitHub Pages as a deployment target.
|
||||
|
||||
| Command | Description |
|
||||
|:--- |:--- |
|
||||
| `npx create-docusaurus@latest www classic` | Scaffold **a new** classic docusaurus site in www/ folder |
|
||||
| `cd www; npm install` | Install dependencies if needed (e.g., fresh clone/fork) |
|
||||
| `cd www; npx docusaurus start` | Preview development site on local device (with hot reload) |
|
||||
| `cd www; npm run build` | Build production-ready site (in _build/_ folder by default) |
|
||||
| `cd www; npm run serve` | Preview production-ready site on local device |
|
||||
| | |
|
||||
|
||||
|
||||
<br/>
|
||||
|
||||
## 2. Customize Site Contents
|
||||
|
||||
We only want to have a Showcase page and a Landing page (for convenience) - so customization is more about removing default features (blog, tutorial) and customizing theme/content.
|
||||
|
||||
| Action | Outcome |
|
||||
|:--- |:--- |
|
||||
| Set `blog: false` in presets under `www/docusaurus.config.js` | Removes blog - establish a [docs-only mode](https://docusaurus.io/docs/docs-introduction#docs-only-mode) with docs as base page. |
|
||||
| Edit themeConfig in `www/docusaurus.config.js` | Removes `Blog` route in navbar. Now delete `www/blog` folder. |
|
||||
| Add `src/pages/showcase.md` page for `/showcase` route | Update themeConfig in `www/docusaurus.config.js` to add it to navbar |
|
||||
| Edit docs sidebar settings in `www/sidebars.js` | Customize [sidebar configuration](https://docusaurus.io/docs/sidebar/items) or learn to use auto-generated versions more effectively. |
|
||||
| Update [styling and layout](https://docusaurus.io/docs/next/styling-layout) and validate for light & dark theme | Use [colorbox.io](https://colorbox.io/) and [guide](https://justtheskills.com/colorbox/) to define color palette. Create [style variables](https://docusaurus.io/docs/next/styling-layout#styling-your-site-with-infima) to update `custom.css` (based on the [infima](https://infima.dev/) styling framework) |
|
||||
| Add [supported plugins](https://docusaurus.io/docs/api/plugins) for enhanced content or behaviors | Default plugins used are [plugin-content-docs](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-docs) (for `docs/` pages) , [plugin-content-blog](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog) (for `blog/`) and [plugin-content-pages](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-pages) for default pages. Check out [plugin-sitemap](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-sitemap), [plugin-ideal-image](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-ideal-image) and [plugin-pwa](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-pwa) for other useful features. |
|
||||
| | |
|
||||
|
||||
<br/>
|
|
@ -1,3 +0,0 @@
|
|||
module.exports = {
|
||||
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
|
||||
};
|
|
@ -1,136 +0,0 @@
|
|||
// @ts-check
|
||||
// Note: type annotations allow type checking and IDEs autocompletion
|
||||
|
||||
const lightCodeTheme = require('prism-react-renderer/themes/github');
|
||||
const darkCodeTheme = require('prism-react-renderer/themes/dracula');
|
||||
|
||||
/** @type {import('@docusaurus/types').Config} */
|
||||
const config = {
|
||||
title: 'Static Web Apps Gallery',
|
||||
tagline: 'A Community Projects & Code Samples Showcase',
|
||||
url: 'https://microsoft.github.io',
|
||||
baseUrl: '/static-web-apps-gallery-code-samples/',
|
||||
onBrokenLinks: 'throw',
|
||||
onBrokenMarkdownLinks: 'warn',
|
||||
favicon: 'img/favicon.ico',
|
||||
organizationName: 'microsoft', // Usually your GitHub org/user name.
|
||||
projectName: 'static-web-apps-gallery-code-samples', // Usually your repo name.
|
||||
trailingSlash: false,
|
||||
deploymentBranch: `gh-pages`, // default = gh-pages
|
||||
|
||||
plugins: [
|
||||
[
|
||||
'@docusaurus/plugin-ideal-image',
|
||||
{
|
||||
quality: 70,
|
||||
max: 1030, // max resized image's size.
|
||||
min: 640, // min resized image's size. if original is lower, use that size.
|
||||
steps: 2, // the max number of images generated between min and max (inclusive)
|
||||
disableInDev: false,
|
||||
},
|
||||
],
|
||||
],
|
||||
|
||||
presets: [
|
||||
[
|
||||
'classic',
|
||||
/** @type {import('@docusaurus/preset-classic').Options} */
|
||||
({
|
||||
docs: false,
|
||||
blog: false,
|
||||
theme: {
|
||||
customCss: require.resolve('./src/css/custom.css'),
|
||||
},
|
||||
}),
|
||||
],
|
||||
],
|
||||
|
||||
themeConfig:
|
||||
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
|
||||
({
|
||||
navbar: {
|
||||
title: 'SWA Gallery',
|
||||
logo: {
|
||||
alt: 'My Site Logo',
|
||||
src: 'img/logo.svg',
|
||||
},
|
||||
items: [
|
||||
{to: '/showcase', label: 'Showcase', position: 'left'},
|
||||
{to: '/contribute', label: 'Contributions', position: 'right'},
|
||||
{to: 'https://github.com/orgs/staticwebdev/discussions/14', label: 'Discussions', position: 'right'},
|
||||
{
|
||||
href: 'https://github.com/microsoft/static-web-apps-gallery-code-samples',
|
||||
position: 'right',
|
||||
className: 'header-github-link',
|
||||
'aria-label': 'GitHub repository',
|
||||
},
|
||||
],
|
||||
},
|
||||
footer: {
|
||||
style: 'dark',
|
||||
links: [
|
||||
{
|
||||
title: 'Discover',
|
||||
items: [
|
||||
{
|
||||
label: 'SWA Docs',
|
||||
to: 'https://docs.microsoft.com/en-us/azure/static-web-apps/overview',
|
||||
},
|
||||
{
|
||||
label: 'SWA CLI',
|
||||
to: 'https://github.com/Azure/static-web-apps-cli',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Learn',
|
||||
items: [
|
||||
{
|
||||
label: 'Learning Path',
|
||||
to: 'https://docs.microsoft.com/en-us/learn/paths/azure-static-web-apps/',
|
||||
},
|
||||
{
|
||||
label: 'Tips & Tricks',
|
||||
to: 'https://docs.microsoft.com/en-us/shows/azure-tips-and-tricks-static-web-apps/',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Connect',
|
||||
items: [
|
||||
{
|
||||
label: 'Dev.to',
|
||||
href: 'https://dev.to/t/staticwebapps',
|
||||
},
|
||||
{
|
||||
label: 'Twitter',
|
||||
href: 'https://twitter.com/AzureStaticApps',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
copyright: `Copyright © ${new Date().getFullYear()} Microsoft - Built with ♥️ using Docusaurus.`,
|
||||
},
|
||||
prism: {
|
||||
theme: lightCodeTheme,
|
||||
darkTheme: darkCodeTheme,
|
||||
},
|
||||
|
||||
image: 'img/logo.png',
|
||||
|
||||
metadata: [{
|
||||
name: 'twitter:card',
|
||||
content: 'Welcome to the Azure Static Web Apps Gallery of community-created projects! Explore the examples - or add your own!'
|
||||
}],
|
||||
announcementBar: {
|
||||
id: 'Add Your Project!',
|
||||
content:
|
||||
'Learn with <a target="_blank" rel="noopener noreferrer" href="https://aka.ms/30DaysOfSWA/"><b>#30DaysOfSWA</b></a> - then <a target="_blank" rel="noopener noreferrer" href="https://portal.azure.com/?feature.customportal=false&WT.mc_id=30daysofswa-61155-ninarasi#create/Microsoft.StaticApp"><b>Deploy To Azure</b>!</a> 🚀',
|
||||
backgroundColor: '#50E6FF',
|
||||
textColor: '#552F99',
|
||||
isCloseable: false,
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
module.exports = config;
|
|
@ -1,39 +0,0 @@
|
|||
{
|
||||
"name": "www",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
"start": "docusaurus start",
|
||||
"build": "docusaurus build",
|
||||
"swizzle": "docusaurus swizzle",
|
||||
"deploy": "docusaurus deploy",
|
||||
"clear": "docusaurus clear",
|
||||
"serve": "docusaurus serve",
|
||||
"write-translations": "docusaurus write-translations",
|
||||
"write-heading-ids": "docusaurus write-heading-ids"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "2.0.0-beta.18",
|
||||
"@docusaurus/plugin-ideal-image": "^2.0.0-beta.18",
|
||||
"@docusaurus/preset-classic": "2.0.0-beta.18",
|
||||
"@mdx-js/react": "^1.6.22",
|
||||
"clsx": "^1.1.1",
|
||||
"prism-react-renderer": "^1.3.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-popper": "^2.2.5"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.5%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
/**
|
||||
* Creating a sidebar enables you to:
|
||||
- create an ordered group of docs
|
||||
- render a sidebar for each doc of that group
|
||||
- provide next/previous navigation
|
||||
|
||||
The sidebars can be generated from the filesystem, or explicitly defined here.
|
||||
|
||||
Create as many sidebars as you want.
|
||||
*/
|
||||
|
||||
// @ts-check
|
||||
|
||||
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
|
||||
const sidebars = {
|
||||
// By default, Docusaurus generates a sidebar from the docs folder structure
|
||||
tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
|
||||
|
||||
// But you can create a sidebar manually
|
||||
/*
|
||||
tutorialSidebar: [
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Tutorial',
|
||||
items: ['hello'],
|
||||
},
|
||||
],
|
||||
*/
|
||||
};
|
||||
|
||||
module.exports = sidebars;
|
|
@ -1,89 +0,0 @@
|
|||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import styles from './styles.module.css';
|
||||
|
||||
const FeatureList = [
|
||||
{
|
||||
title: 'Angular',
|
||||
Svg: require('@site/static/img/logo.svg').default,
|
||||
link: "showcase?tags=angular",
|
||||
},
|
||||
{
|
||||
title: 'Gatsby',
|
||||
Svg: require('@site/static/img/logo.svg').default,
|
||||
link: "showcase?tags=gatsby",
|
||||
},
|
||||
{
|
||||
title: 'Hugo',
|
||||
Svg: require('@site/static/img/logo.svg').default,
|
||||
link: "showcase?tags=hugo",
|
||||
},
|
||||
{
|
||||
title: 'Jekyll',
|
||||
Svg: require('@site/static/img/logo.svg').default,
|
||||
link: "showcase?tags=jekyll",
|
||||
},
|
||||
{
|
||||
title: 'Next.js',
|
||||
Svg: require('@site/static/img/logo.svg').default,
|
||||
link: "showcase?tags=next",
|
||||
},
|
||||
{
|
||||
title: 'Nuxt.js',
|
||||
Svg: require('@site/static/img/logo.svg').default,
|
||||
link: "showcase?tags=nuxt",
|
||||
},
|
||||
{
|
||||
title: 'Svelte',
|
||||
Svg: require('@site/static/img/logo.svg').default,
|
||||
link: "showcase?tags=svelte",
|
||||
},
|
||||
{
|
||||
title: 'React',
|
||||
Svg: require('@site/static/img/logo.svg').default,
|
||||
link: "showcase?tags=react",
|
||||
},
|
||||
{
|
||||
title: 'Vue.js',
|
||||
Svg: require('@site/static/img/logo.svg').default,
|
||||
link: "showcase?tags=vuejs",
|
||||
},
|
||||
];
|
||||
|
||||
function Feature({Svg, title, link}) {
|
||||
return (
|
||||
<div className={clsx('col col--4')}>
|
||||
<a href={link}>
|
||||
<div className="text--center padding-horiz--md">
|
||||
{/* <Svg className={styles.featureSvg} role="img" /> */}
|
||||
<h3>{title}</h3>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function HomepageFeatures() {
|
||||
return (
|
||||
<section className={styles.features}>
|
||||
<div className="container">
|
||||
<div className="row padding-horiz--md">
|
||||
<h2>Welcome to The Static Web Apps Gallery</h2>
|
||||
</div>
|
||||
<div className="row padding-horiz--md">
|
||||
This is a showcase of community-created projects that use Azure Static Web Apps (SWA) to simplify their build-deploy experience. Explore the gallery to view deployed versions for various front-end frameworks and static site generators. Visit the Contributions page for guidelines, and share your questions and comments with us on the Discussions page.
|
||||
</div>
|
||||
<br/>
|
||||
<div className="row padding-horiz--md">
|
||||
Here are a few of the popular frameworks you can use to build Static Web Apps. Click on one to view the Showcase filtered by that technology.
|
||||
</div>
|
||||
<hr/>
|
||||
<div className="row">
|
||||
{FeatureList.map((props, idx) => (
|
||||
<Feature key={idx} {...props} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
.features {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 2rem 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.featureSvg {
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {type ReactNode, type ComponentProps} from 'react';
|
||||
import clsx from 'clsx';
|
||||
import styles from './styles.module.css';
|
||||
|
||||
export type SvgIconProps = ComponentProps<'svg'> & {
|
||||
viewBox?: string;
|
||||
size?: 'inherit' | 'small' | 'medium' | 'large';
|
||||
color?: 'inherit' | 'primary' | 'secondary' | 'success' | 'error' | 'warning';
|
||||
svgClass?: string; // Class attribute on the child
|
||||
colorAttr?: string; // Applies a color attribute to the SVG element.
|
||||
children: ReactNode; // Node passed into the SVG element.
|
||||
};
|
||||
|
||||
export default function Svg(props: SvgIconProps): JSX.Element {
|
||||
const {
|
||||
svgClass,
|
||||
colorAttr,
|
||||
children,
|
||||
color = 'inherit',
|
||||
size = 'medium',
|
||||
viewBox = '0 0 24 24',
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<svg
|
||||
viewBox={viewBox}
|
||||
color={colorAttr}
|
||||
aria-hidden
|
||||
className={clsx(styles.svgIcon, styles[color], styles[size], svgClass)}
|
||||
{...rest}>
|
||||
{children}
|
||||
</svg>
|
||||
);
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
.svgIcon {
|
||||
user-select: none;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
display: inline-block;
|
||||
fill: currentColor;
|
||||
flex-shrink: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* font-size */
|
||||
.small {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.medium {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.large {
|
||||
font-size: 2.185rem;
|
||||
}
|
||||
|
||||
/* colors */
|
||||
.primary {
|
||||
color: var(--ifm-color-primary);
|
||||
}
|
||||
|
||||
.secondary {
|
||||
color: var(--ifm-color-secondary);
|
||||
}
|
||||
|
||||
.success {
|
||||
color: var(--ifm-color-success);
|
||||
}
|
||||
|
||||
.error {
|
||||
color: var(--ifm-color-error);
|
||||
}
|
||||
|
||||
.warning {
|
||||
color: var(--ifm-color-warning);
|
||||
}
|
||||
|
||||
.inherit {
|
||||
color: inherit;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Svg, {type SvgIconProps} from '@site/src/components/Svg';
|
||||
|
||||
export default function FavoriteIcon(
|
||||
props: Omit<SvgIconProps, 'children'>,
|
||||
): JSX.Element {
|
||||
return (
|
||||
<Svg {...props}>
|
||||
<path d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z" />
|
||||
</Svg>
|
||||
);
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
/**
|
||||
* Any CSS included here will be global. The classic template
|
||||
* bundles Infima by default. Infima is a CSS framework designed to
|
||||
* work well for content-centric websites.
|
||||
*/
|
||||
|
||||
/* You can override the default Infima variables here. */
|
||||
:root {
|
||||
/*
|
||||
See default settings (css vars etc.) in docusaurus site (for Showcase elements)
|
||||
https://github.com/facebook/docusaurus/blob/main/website/src/css/custom.css
|
||||
TODO: review and prune for minimal settings needed
|
||||
----
|
||||
See css var + hsl color palette technique:
|
||||
https://blog.maximeheckel.com/posts/the-power-of-composition-with-css-variables/
|
||||
*/
|
||||
--site-primary-hue-saturation: 167 68%;
|
||||
--site-primary-hue-saturation-light: 167 56%; /* do we really need this extra one? */
|
||||
--site-color-favorite-background: #f6fdfd;
|
||||
--site-color-tooltip: #fff;
|
||||
--site-color-tooltip-background: #353738;
|
||||
--site-color-svg-icon-favorite: #e9669e;
|
||||
--site-color-checkbox-checked-bg: hsl(167deg 56% 73% / 25%);
|
||||
--site-color-feedback-background: #fff;
|
||||
--docusaurus-highlighted-code-line-bg: rgb(0 0 0 / 10%);
|
||||
}
|
||||
|
||||
[data-theme='light'] {
|
||||
--ifm-color-primary: #552f99;
|
||||
--ifm-color-primary-dark: #4d2a8a;
|
||||
--ifm-color-primary-darker: #482882;
|
||||
--ifm-color-primary-darkest: #3c216b;
|
||||
--ifm-color-primary-light: #5e34a8;
|
||||
--ifm-color-primary-lighter: #6236b0;
|
||||
--ifm-color-primary-lightest: #6f40c4;
|
||||
}
|
||||
|
||||
/* For readability concerns, you should choose a lighter palette in dark mode. */
|
||||
[data-theme='dark'] {
|
||||
--ifm-color-primary: #50e6ff;
|
||||
--ifm-color-primary-dark: #2fe1ff;
|
||||
--ifm-color-primary-darker: #1edfff;
|
||||
--ifm-color-primary-darkest: #00c9eb;
|
||||
--ifm-color-primary-light: #72ebff;
|
||||
--ifm-color-primary-lighter: #82edff;
|
||||
--ifm-color-primary-lightest: #b4f4ff;
|
||||
}
|
||||
|
||||
.docusaurus-highlight-code-line {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
display: block;
|
||||
margin: 0 calc(-1 * var(--ifm-pre-padding));
|
||||
padding: 0 var(--ifm-pre-padding);
|
||||
}
|
||||
|
||||
[data-theme='dark'] .docusaurus-highlight-code-line {
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
|
||||
.header-github-link:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.header-github-link::before {
|
||||
content: '';
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
|
||||
no-repeat;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .header-github-link::before {
|
||||
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
|
||||
no-repeat;
|
||||
}
|
||||
|
||||
/* Used in Showcase-Card */
|
||||
.screen-reader-only {
|
||||
border: 0;
|
||||
clip: rect(0 0 0 0);
|
||||
clip-path: polygon(0 0, 0 0, 0 0);
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
white-space: nowrap;
|
||||
}
|
Двоичные данные
docs/www/src/data/showcase/11ty.png
До Ширина: | Высота: | Размер: 491 KiB |
Двоичные данные
docs/www/src/data/showcase/angular-rock-paper-scissors.png
До Ширина: | Высота: | Размер: 141 KiB |
Двоичные данные
docs/www/src/data/showcase/angular-ssr.png
До Ширина: | Высота: | Размер: 225 KiB |
Двоичные данные
docs/www/src/data/showcase/angular-swa-auth.gif
До Ширина: | Высота: | Размер: 2.0 MiB |
Двоичные данные
docs/www/src/data/showcase/azure_vision.gif
До Ширина: | Высота: | Размер: 4.9 MiB |
Двоичные данные
docs/www/src/data/showcase/catsify.png
До Ширина: | Высота: | Размер: 430 KiB |
Двоичные данные
docs/www/src/data/showcase/cognitive-search-demo.png
До Ширина: | Высота: | Размер: 603 KiB |
Двоичные данные
docs/www/src/data/showcase/docusaurus-starter.PNG
До Ширина: | Высота: | Размер: 36 KiB |
Двоичные данные
docs/www/src/data/showcase/gatsby_starter.png
До Ширина: | Высота: | Размер: 53 KiB |
Двоичные данные
docs/www/src/data/showcase/hexa.png
До Ширина: | Высота: | Размер: 826 KiB |
Двоичные данные
docs/www/src/data/showcase/mayadb.png
До Ширина: | Высота: | Размер: 280 KiB |
Двоичные данные
docs/www/src/data/showcase/meme4fun.gif
До Ширина: | Высота: | Размер: 2.4 MiB |
Двоичные данные
docs/www/src/data/showcase/mongoose-starter.png
До Ширина: | Высота: | Размер: 11 KiB |
Двоичные данные
docs/www/src/data/showcase/mongoose.png
До Ширина: | Высота: | Размер: 48 KiB |
Двоичные данные
docs/www/src/data/showcase/ngvikings2020.png
До Ширина: | Высота: | Размер: 616 KiB |
Двоичные данные
docs/www/src/data/showcase/ngxtools.png
До Ширина: | Высота: | Размер: 1.0 MiB |
Двоичные данные
docs/www/src/data/showcase/nitro.png
До Ширина: | Высота: | Размер: 34 KiB |
Двоичные данные
docs/www/src/data/showcase/nitrooo.png
До Ширина: | Высота: | Размер: 62 KiB |
Двоичные данные
docs/www/src/data/showcase/peacock-icon.png
До Ширина: | Высота: | Размер: 14 KiB |
Двоичные данные
docs/www/src/data/showcase/posedance.png
До Ширина: | Высота: | Размер: 786 KiB |
Двоичные данные
docs/www/src/data/showcase/positive-quote.png
До Ширина: | Высота: | Размер: 3.1 MiB |
Двоичные данные
docs/www/src/data/showcase/pwablog.png
До Ширина: | Высота: | Размер: 578 KiB |
Двоичные данные
docs/www/src/data/showcase/shop-at-home-svelte.png
До Ширина: | Высота: | Размер: 51 KiB |
Двоичные данные
docs/www/src/data/showcase/stencil.png
До Ширина: | Высота: | Размер: 185 KiB |
Двоичные данные
docs/www/src/data/showcase/sunrise-standup.png
До Ширина: | Высота: | Размер: 249 KiB |
Двоичные данные
docs/www/src/data/showcase/user.png
До Ширина: | Высота: | Размер: 9.5 KiB |
Двоичные данные
docs/www/src/data/showcase/vscodecandothat.png
До Ширина: | Высота: | Размер: 438 KiB |
Двоичные данные
docs/www/src/data/showcase/xlayers-1.png
До Ширина: | Высота: | Размер: 1.4 MiB |
Двоичные данные
docs/www/src/data/showcase/xlayers-2.png
До Ширина: | Высота: | Размер: 1.4 MiB |
|
@ -1,276 +0,0 @@
|
|||
/*
|
||||
* ADD YOUR SITE TO THE DOCUSAURUS SHOWCASE:
|
||||
*
|
||||
* Requirements for adding your site to our showcase:
|
||||
* - It is a production-ready site with real content and decent customizations
|
||||
* (different from the init templates)
|
||||
* - It is NOT a work-in-progress with empty pages
|
||||
* - It has a stable domain (a Netlify/Vercel deploy preview is not allowed)
|
||||
*
|
||||
* Instructions:
|
||||
* - Add your site in the json array below
|
||||
* - `title` is your project's name (no need for the "Docs" suffix)
|
||||
* - A short (≤120 characters) description of your project
|
||||
* - Use relevant tags to categorize your site (read the tag descriptions below)
|
||||
* - Add a local image preview (decent screenshot of your Docusaurus site)
|
||||
* - The image MUST be added to the GitHub repository, and use `require("img")`
|
||||
* - The image has to have minimum width 640 and an aspect of no wider than 2:1
|
||||
* - If your website is open-source, add your source link. The link should open
|
||||
* to a directory containing the `docusaurus.config.js` file
|
||||
* - Open a PR and check for reported CI errors
|
||||
*
|
||||
* Example PR: https://github.com/facebook/docusaurus/pull/3976
|
||||
*
|
||||
* If you edit this file through the GitHub interface, you can:
|
||||
* - Submit first your users.tsx edit PR
|
||||
* - This will create a branch on your Docusaurus fork (usually "patch-1")
|
||||
* - Go to https://github.com/<username>/docusaurus/tree/<branch>/website/src/data/showcase
|
||||
* - Drag-and-drop an image here to add it to your existing PR
|
||||
*
|
||||
* Please help us maintain this showcase page data:
|
||||
* - Update sites with wrong data
|
||||
* - Ensure site tags remain correct over time
|
||||
* - Remove sites not using Docusaurus anymore
|
||||
* - Add missing Docusaurus sites (if the site owner agreed)
|
||||
*/
|
||||
|
||||
export type Tag = {
|
||||
label: string;
|
||||
description: string;
|
||||
color: string;
|
||||
};
|
||||
|
||||
// NN: Updated TagType to suit Static Web Apps
|
||||
export type TagType =
|
||||
| 'favorite'
|
||||
| 'opensource'
|
||||
| 'archived'
|
||||
| 'angular'
|
||||
| 'astro'
|
||||
| 'blazor'
|
||||
| 'cognitive-services'
|
||||
| 'docusaurus'
|
||||
| 'eleventy'
|
||||
| 'fast'
|
||||
| 'gatsby'
|
||||
| 'gridsome'
|
||||
| 'hugo'
|
||||
| 'jekyll'
|
||||
| 'lit'
|
||||
| 'next'
|
||||
| 'npm'
|
||||
| 'nuxt'
|
||||
| 'pwa'
|
||||
| 'react'
|
||||
| 'remix'
|
||||
| 'scully'
|
||||
| 'svelte'
|
||||
| 'vanillajs'
|
||||
| 'vuejs'
|
||||
| 'vuepress';
|
||||
|
||||
export type User = {
|
||||
title: string;
|
||||
description: string;
|
||||
preview: string;
|
||||
website: string;
|
||||
source: string | null;
|
||||
tags: TagType[];
|
||||
};
|
||||
|
||||
// LIST OF AVAILABLE TAGS
|
||||
// Available tags to assign to your site
|
||||
// Please choose all tags that you think might apply.
|
||||
// We'll remove inappropriate tags,
|
||||
// but it's less likely that we add tags.
|
||||
export const Tags: {[type in TagType]: Tag} = {
|
||||
|
||||
// DO NOT USE THIS TAG: we choose sites to add to favorites
|
||||
favorite: {
|
||||
label: 'Favorite',
|
||||
description:
|
||||
'Some must-see Static Web App Examples that we loved!!',
|
||||
color: '#ffd60a', //'#e9669e',
|
||||
},
|
||||
|
||||
// For open-source sites, a link to the source code is required
|
||||
// The source should be your *website's* source, not your project's source!
|
||||
opensource: {
|
||||
label: 'Open Source',
|
||||
description: 'This SWA example has source code available to learn from and build upon!',
|
||||
color: '#00ff00',
|
||||
},
|
||||
|
||||
// This tag indicates the website is not currently live
|
||||
// Tag may be added AUTOMATICALLY by scripted checks
|
||||
// Intent is to keep historical contributions for other value
|
||||
// e.g., source/screenshot - till owner or maintainer decides
|
||||
// to remove them for other reasons.
|
||||
archived: {
|
||||
label: 'Archived',
|
||||
description: 'Au',
|
||||
color: '#ff0000',
|
||||
},
|
||||
|
||||
angular: {
|
||||
label: 'Angular',
|
||||
description:
|
||||
'Using Angular Framework (https://angular.io)',
|
||||
color: '#ffd300',
|
||||
},
|
||||
|
||||
astro: {
|
||||
label: 'Astro',
|
||||
description:
|
||||
'Using Astro Static Site Generator (https://astro.build)',
|
||||
color: '#deff0a',
|
||||
},
|
||||
|
||||
blazor: {
|
||||
label: 'Blazor',
|
||||
description:
|
||||
'Using Blazor with WASM (https://blazor.net)',
|
||||
color: '#a1ff0a',
|
||||
},
|
||||
|
||||
"cognitive-services": {
|
||||
label: 'Azure Cogntive Services',
|
||||
description:
|
||||
'Using Azure Cognitive Services for speech, vision and other capabilities.',
|
||||
color: '#f0f0f0',
|
||||
},
|
||||
|
||||
docusaurus: {
|
||||
label: 'Docusaurus',
|
||||
description:
|
||||
'Using Docusaurus Static Site Generator (https://docusaurus.io)',
|
||||
color: '#a1ff0a',
|
||||
},
|
||||
|
||||
eleventy: {
|
||||
label: '11ty',
|
||||
description:
|
||||
'Using 11ty Static Site Generator (https://www.11ty.dev/)',
|
||||
color: '#0aff99',
|
||||
},
|
||||
|
||||
fast: {
|
||||
label: 'fast',
|
||||
description:
|
||||
'Using Fast Web Components (https://www.fast.design/)',
|
||||
color: '#0aefff',
|
||||
},
|
||||
|
||||
gatsby: {
|
||||
label: 'Gatsby',
|
||||
description:
|
||||
'Using the React-powered Static Site Generator (https://www.gatsbyjs.com/)',
|
||||
color: '#147df5',
|
||||
},
|
||||
|
||||
gridsome: {
|
||||
label: 'Gridsome',
|
||||
description:
|
||||
'Using the Vue-powered Static Site Generator (https://gridsome.org/)',
|
||||
color: '#580aff',
|
||||
},
|
||||
|
||||
hugo: {
|
||||
label: 'Hugo',
|
||||
description:
|
||||
'Using the Go-powered Static Site Generator (https://www.gohugo.io/)',
|
||||
color: '#70d6ff',
|
||||
},
|
||||
|
||||
jekyll: {
|
||||
label: 'Jekyll',
|
||||
description:
|
||||
'Using the Markdown-friendly Static Site Generator (http://jekyllrb.com/)',
|
||||
color: '#70d6ff',
|
||||
},
|
||||
|
||||
lit: {
|
||||
label: 'Lit',
|
||||
description:
|
||||
'Using the Lit Web Components (https://lit.dev/)',
|
||||
color: '#ff9770',
|
||||
},
|
||||
|
||||
next: {
|
||||
label: 'Next.js',
|
||||
description:
|
||||
'Using the React-powered Framework (https://nextjs.org/)',
|
||||
color: '#ffd670',
|
||||
},
|
||||
|
||||
npm: {
|
||||
label: 'npm',
|
||||
description:
|
||||
'Apps showcasing usage of npm packages',
|
||||
color: '#ffaabb',
|
||||
},
|
||||
|
||||
nuxt: {
|
||||
label: 'Nuxt.js',
|
||||
description:
|
||||
'Using the Vue-powered Framework (https://nuxtjs.org//)',
|
||||
color: '#e9ff70',
|
||||
},
|
||||
|
||||
pwa: {
|
||||
label: 'PWA',
|
||||
description:
|
||||
'Also showcases an example of Progressive Web Apps',
|
||||
color: '#deff0a',
|
||||
},
|
||||
|
||||
react: {
|
||||
label: 'React',
|
||||
description:
|
||||
'Using React UI Framework (https://reactjs.org)',
|
||||
color: '#809bce',
|
||||
},
|
||||
|
||||
remix: {
|
||||
label: 'Remix',
|
||||
description:
|
||||
'Using the Remix full-stack framework (https://remix.run/)',
|
||||
color: '#95b8d1',
|
||||
},
|
||||
|
||||
scully: {
|
||||
label: 'Scully',
|
||||
description:
|
||||
'Using Angular-powered Static Site Generator (https://scully.io/)',
|
||||
color: '#95b8d1',
|
||||
},
|
||||
|
||||
svelte: {
|
||||
label: 'Svelte',
|
||||
description:
|
||||
'Using Svelte Framework (https://svelte.dev/)',
|
||||
color: '#95b8d1',
|
||||
},
|
||||
|
||||
vanillajs: {
|
||||
label: 'Vanilla JS',
|
||||
description:
|
||||
'Using Vanilla JS/HTML/CSS',
|
||||
color: '#95b8d1',
|
||||
},
|
||||
|
||||
vuejs: {
|
||||
label: 'Vue JS',
|
||||
description:
|
||||
'Using Vue.js Framework (https://vuejs.org)',
|
||||
color: '#bc8a5f',
|
||||
},
|
||||
|
||||
vuepress: {
|
||||
label: 'VuePress',
|
||||
description:
|
||||
'Using Vue-powered Static Site Generator (https://vuepress.vuejs.org/)',
|
||||
color: '#8b5e34',
|
||||
},
|
||||
};
|
||||
|
|
@ -1,231 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/* eslint-disable global-require */
|
||||
|
||||
import {sortBy} from '@site/src/utils/jsUtils';
|
||||
import {TagType, User, Tags} from './tags';
|
||||
|
||||
/*
|
||||
* ADD YOUR SITE TO THE DOCUSAURUS SHOWCASE:
|
||||
*
|
||||
* Requirements for adding your site to our showcase:
|
||||
* - It is a production-ready site with real content and decent customizations
|
||||
* (different from the init templates)
|
||||
* - It is NOT a work-in-progress with empty pages
|
||||
* - It has a stable domain (a Netlify/Vercel deploy preview is not allowed)
|
||||
*
|
||||
* Instructions:
|
||||
* - Add your site in the json array below
|
||||
* - `title` is your project's name (no need for the "Docs" suffix)
|
||||
* - A short (≤120 characters) description of your project
|
||||
* - Use relevant tags to categorize your site (read the tag descriptions below)
|
||||
* - Add a local image preview (decent screenshot of your Docusaurus site)
|
||||
* - The image MUST be added to the GitHub repository, and use `require("img")`
|
||||
* - The image has to have minimum width 640 and an aspect of no wider than 2:1
|
||||
* - If your website is open-source, add your source link. The link should open
|
||||
* to a directory containing the `docusaurus.config.js` file
|
||||
* - Open a PR and check for reported CI errors
|
||||
*
|
||||
* Example PR: https://github.com/facebook/docusaurus/pull/3976
|
||||
*
|
||||
* If you edit this file through the GitHub interface, you can:
|
||||
* - Submit first your users.tsx edit PR
|
||||
* - This will create a branch on your Docusaurus fork (usually "patch-1")
|
||||
* - Go to https://github.com/<username>/docusaurus/tree/<branch>/website/src/data/showcase
|
||||
* - Drag-and-drop an image here to add it to your existing PR
|
||||
*
|
||||
* Please help us maintain this showcase page data:
|
||||
* - Update sites with wrong data
|
||||
* - Ensure site tags remain correct over time
|
||||
* - Remove sites not using Docusaurus anymore
|
||||
* - Add missing Docusaurus sites (if the site owner agreed)
|
||||
*/
|
||||
|
||||
|
||||
// *************** USER ENTERED DATA STARTS HERE *********************************
|
||||
// Add your site to this list
|
||||
// prettier-ignore
|
||||
const Users: User[] = [
|
||||
/*
|
||||
Pro Tip: add your site in alphabetical order.
|
||||
Appending your site at the end (of list) is more likely to produce Git conflicts.
|
||||
*/
|
||||
/*
|
||||
{
|
||||
title: '',
|
||||
description:
|
||||
'',
|
||||
preview: require('./showcase/catsify.png'),
|
||||
website: '',
|
||||
source: '',
|
||||
tags: ['FRONT-END','opensource'],
|
||||
},
|
||||
*/
|
||||
|
||||
{
|
||||
title: 'Angular SWA Auth',
|
||||
description:
|
||||
'Demo app showcasing the use of the npm package angular-swa-auth',
|
||||
preview: require('./showcase/angular-swa-auth.gif'),
|
||||
website: 'https://angular-swa-auth.codingdemo.co.uk/',
|
||||
source: 'https://github.com/christianacca/static-web-apps-auth',
|
||||
tags: ['angular','opensource', 'npm'],
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Catsify',
|
||||
description:
|
||||
'A cat names generator built with Angular',
|
||||
preview: require('./showcase/catsify.png'),
|
||||
website: 'https://www.catsify.app/',
|
||||
source: 'https://github.com/manekinekko/catsify',
|
||||
tags: ['angular', 'opensource'],
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Cognitive Search SWA Demo',
|
||||
description:
|
||||
'A sample faceted search user experience implementation for your Azure Cognitive Search index. Similar to the official demo app, but a bit more modern. ',
|
||||
preview: require('./showcase/cognitive-search-demo.png'),
|
||||
website: 'https://lively-sand-033e9ec03.azurestaticapps.net/',
|
||||
source: 'https://github.com/scale-tone/cognitive-search-static-web-apps-sample-ui',
|
||||
tags: ['react','opensource'],
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Docusaurus Starter',
|
||||
description:
|
||||
'A simple starter template for creating documentation website using the Docusaurus framework.',
|
||||
preview: require('./showcase/docusaurus-starter.png'),
|
||||
website: 'https://ambitious-pebble-02b2d3010.azurestaticapps.net/',
|
||||
source: 'https://github.com/sumitkharche/docusaurus-swa-app',
|
||||
tags: ['docusaurus','opensource'],
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Hexa CLI Landing Page',
|
||||
description:
|
||||
'Hexa is the ultimate companion for the Azure CLI. It allows you to seamlessly configure, setup and deploy to different Azure services such as Resource Groups, Storage accounts, Hosting, Azure Functions and Databases (CosmosDB and Table Storage) and more.',
|
||||
preview: require('./showcase/hexa.png'),
|
||||
website: 'https://www.hexa.run/',
|
||||
source: 'https://github.com/manekinekko/hexa/',
|
||||
tags: ['vanillajs','opensource'],
|
||||
},
|
||||
|
||||
{
|
||||
title: 'ngVikings Conference',
|
||||
description:
|
||||
'ngVikings is a non-profit, non-commercial, 100% community-driven event comprised of many Nordic Angular groups with more than 6500 active members in total.',
|
||||
preview: require('./showcase/ngvikings2020.png'),
|
||||
website: 'https://www.ngvikings.org/',
|
||||
source: 'https://github.com/ngvikings/ngvikings-2020',
|
||||
tags: ['hugo','opensource','pwa'],
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Nitroo Landing Page',
|
||||
description:
|
||||
'Nitro is a heavily opinionated template for building Serverless applications with NestJS, the fastest-growing NodeJS framework in the world by github stars.',
|
||||
preview: require('./showcase/nitrooo.png'),
|
||||
website: 'https://victorious-ocean-0337ef81e.azurestaticapps.net/',
|
||||
source: 'https://github.com/nitro-stack/website',
|
||||
tags: ['vanillajs','opensource'],
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Nitro Workshop',
|
||||
description:
|
||||
'Online workshop built with Vuepress to learn how to build a backend using NestJS. This is a practical workshop where you\'ll learn "hands-on" by iteratively building an application from scratch using NestJS and Azure.',
|
||||
preview: require('./showcase/nitro.png'),
|
||||
website: 'https://nitro-stack.github.io/nitro-workshop/',
|
||||
source: 'https://github.com/nitro-stack/nitro-workshop',
|
||||
tags: ['vuepress','opensource'],
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Peacock for Visual Studio Code Documentation',
|
||||
description:
|
||||
'Peacock is a Visual Studio Code extension with 700,000+ installations. It subtly changes the color of your Visual Studio Code workspace. This is ideal when you have multiple VS Code instances, use VS Live Share, or use VS Code\'s Remote features, and you want to quickly identify your editor.',
|
||||
preview: require('./showcase/peacock-icon.png'),
|
||||
website: 'https://www.peacockcode.dev/',
|
||||
source: 'https://github.com/johnpapa/vscode-peacock',
|
||||
tags: ['vuepress','opensource'],
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Positive Thought For The Day',
|
||||
description:
|
||||
'A simple demo for Azure SWAG (Static Web Apps on GitHub) that you can use as a template for your own apps.',
|
||||
preview: require('./showcase/positive-quote.png'),
|
||||
website: 'https://aka.ms/swag-demo',
|
||||
source: 'https://github.com/sinedied/azure-swag/',
|
||||
tags: ['vanillajs','opensource','favorite'],
|
||||
},
|
||||
|
||||
{
|
||||
title: 'PWA Blog',
|
||||
description:
|
||||
'News and articles about Progressive Web Apps. By Maxim Salnikov',
|
||||
preview: require('./showcase/pwablog.png'),
|
||||
website: 'https://www.webmax.ru/',
|
||||
source: 'https://github.com/webmaxru/webmax.ru',
|
||||
tags: ['scully','opensource','pwa'],
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Rock Paper Scissors',
|
||||
description:
|
||||
'Play the well known game of Rock-Paper-Scissors. Opponent moves are simulated by an Azure Function. Built with Angular by @stuartleaveruk',
|
||||
preview: require('./showcase/angular-rock-paper-scissors.png'),
|
||||
website: '',
|
||||
source: 'https://github.com/stuartleaver/rock-paper-scissors-static-web-app',
|
||||
tags: ['angular', 'opensource','archived'],
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Shop At Home',
|
||||
description:
|
||||
'"Shop at Home" is a sample app which is written in four variations: Angular, React, Svelte and Vue. It is shown in the Build 2020 video presentation.',
|
||||
preview: require('./showcase/shop-at-home-svelte.png'),
|
||||
website: 'https://www.shopathome.dev/',
|
||||
source: 'https://github.com/johnpapa/shopathome',
|
||||
tags: ['svelte','opensource'],
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
title: 'VS Code Can Do That?',
|
||||
description:
|
||||
'All the best things about VS Code that nobody ever bothered to show you.',
|
||||
preview: require('./showcase/vscodecandothat.png'),
|
||||
website: 'https://www.vscodecandothat.com/',
|
||||
source: 'https://github.com/burkeholland/vscodecandothat/',
|
||||
tags: ['vanillajs','opensource', 'favorite'],
|
||||
},
|
||||
|
||||
/*
|
||||
Pro Tip: add your site in alphabetical order.
|
||||
Appending your site here (at the end) is more likely to produce Git conflicts.
|
||||
*/
|
||||
];
|
||||
// *************** USER ENTERED DATA ENDS HERE *********************************
|
||||
|
||||
|
||||
|
||||
|
||||
export const TagList = Object.keys(Tags) as TagType[];
|
||||
function sortUsers() {
|
||||
let result = Users;
|
||||
// Sort by site name
|
||||
result = sortBy(result, (user) => user.title.toLowerCase());
|
||||
// Sort by favorite tag, favorites first
|
||||
result = sortBy(result, (user) => !user.tags.includes('favorite'));
|
||||
return result;
|
||||
}
|
||||
|
||||
export const sortedUsers = sortUsers();
|
|
@ -1,41 +0,0 @@
|
|||
# Add Project To Showcase
|
||||
|
||||
Start by reading our [Contributors Guide](https://github.com/microsoft/static-web-apps-gallery-code-samples/blob/master/CONTRIBUTING.md) and our [Code of Conduct](https://github.com/microsoft/static-web-apps-gallery-code-samples/blob/master/CODE_OF_CONDUCT.md). If you still want to contribute, check the requirements for adding a new project, then follow the Process to make your submission.
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
We want to feature useful examples of Static Web Apps sites in action.
|
||||
* The site must be deployed using Azure Static Web Apps.
|
||||
* The site must be live (active) and functional at submission time.
|
||||
* The site must showcase some key feature or use case (beyond boilerplate)
|
||||
|
||||
Bonus Features:
|
||||
* The site has a custom domain.
|
||||
* The app is deployed in production.
|
||||
* The app uses a new framework or generator (first example)
|
||||
|
||||
---
|
||||
|
||||
## Process
|
||||
|
||||
[**For this repository**](https://github.com/microsoft/static-web-apps-gallery-code-samples/)
|
||||
* Follow instructions in the `docs/www/src/data/users.tsx` file
|
||||
* Don't forget to add relevant screenshots in `data/showcase`
|
||||
* Be respectful of others content when naming your files
|
||||
* Submit the PR for approval.
|
||||
|
||||
---
|
||||
|
||||
## Maintenance
|
||||
|
||||
If your app status changes at any time, please update the submission entry (or delete it and related screenshots, if no longer compliant to requirements). Your help in keeping this repository relevant is much appreciated.
|
||||
|
||||
---
|
||||
|
||||
## Archived Tag
|
||||
|
||||
We will periodically verify the links associated with a project submission to ensure they are active and accessible. If a provided source or deployment link fails, that project will be tagged `archived` in the Showcase. We reserve the right to remove or de-prioritize display of archived projects in the future.
|
||||
|
||||
---
|
|
@ -1,42 +0,0 @@
|
|||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Layout from '@theme/Layout';
|
||||
import Link from '@docusaurus/Link';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import styles from './index.module.css';
|
||||
import HomepageFeatures from '@site/src/components/HomepageFeatures';
|
||||
|
||||
|
||||
function HomepageHeader() {
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
return (
|
||||
<header className={clsx('hero hero--primary', styles.heroBanner)}>
|
||||
<div className="container">
|
||||
<h1 className="hero__title">{siteConfig.title}</h1>
|
||||
<p className="hero__subtitle">{siteConfig.tagline}</p>
|
||||
<div className={styles.buttons}>
|
||||
<Link
|
||||
className="button button--secondary button--lg"
|
||||
to="/contribute">
|
||||
Explore the Gallery 🔎
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default function Home() {
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
return (
|
||||
<Layout
|
||||
title={`Hello from ${siteConfig.title}`}
|
||||
description="Description will go into a meta tag in <head />">
|
||||
{<HomepageHeader />}
|
||||
<main>
|
||||
<HomepageFeatures />
|
||||
</main>
|
||||
</Layout>
|
||||
);
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
/**
|
||||
* CSS files with the .module.css suffix will be treated as CSS modules
|
||||
* and scoped locally.
|
||||
*/
|
||||
|
||||
.heroBanner {
|
||||
padding: 4rem 0;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 996px) {
|
||||
.heroBanner {
|
||||
padding: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
MIT License
|
||||
|
||||
(From: https://github.com/facebook/docusaurus/blob/main/LICENSE)
|
||||
|
||||
Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -1,100 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Image from '@theme/IdealImage';
|
||||
import Link from '@docusaurus/Link';
|
||||
import Translate from '@docusaurus/Translate';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
import FavoriteIcon from '@site/src/components/svgIcons/FavoriteIcon';
|
||||
import Tooltip from '../ShowcaseTooltip';
|
||||
import {
|
||||
Tag,
|
||||
Tags,
|
||||
type User,
|
||||
type TagType,
|
||||
} from '@site/src/data/tags';
|
||||
import {
|
||||
TagList,
|
||||
} from '@site/src/data/users';
|
||||
import {sortBy} from '@site/src/utils/jsUtils';
|
||||
|
||||
const TagComp = React.forwardRef<HTMLLIElement, Tag>(
|
||||
({label, color, description}, ref) => (
|
||||
<li ref={ref} className={styles.tag} title={description}>
|
||||
<span className={styles.textLabel}>{label.toLowerCase()}</span>
|
||||
<span className={styles.colorLabel} style={{backgroundColor: color}} />
|
||||
</li>
|
||||
),
|
||||
);
|
||||
|
||||
function ShowcaseCardTag({tags}: {tags: TagType[]}) {
|
||||
const tagObjects = tags.map((tag) => ({tag, ...Tags[tag]}));
|
||||
|
||||
// Keep same order for all tags
|
||||
const tagObjectsSorted = sortBy(tagObjects, (tagObject) =>
|
||||
TagList.indexOf(tagObject.tag),
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{tagObjectsSorted.map((tagObject, index) => {
|
||||
const id = `showcase_card_tag_${tagObject.tag}`;
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
key={index}
|
||||
text={tagObject.description}
|
||||
anchorEl="#__docusaurus"
|
||||
id={id}>
|
||||
<TagComp key={index} {...tagObject} />
|
||||
</Tooltip>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ShowcaseCard({user}: {user: User}) {
|
||||
return (
|
||||
<li key={user.title} className="card shadow--md">
|
||||
<div className={clsx('card__image', styles.showcaseCardImage)}>
|
||||
<Image img={user.preview} alt={user.title} />
|
||||
</div>
|
||||
<div className="card__body">
|
||||
<div className={clsx(styles.showcaseCardHeader)}>
|
||||
<h4 className={styles.showcaseCardTitle}>
|
||||
<Link href={user.website} className={styles.showcaseCardLink}>
|
||||
{user.title}
|
||||
</Link>
|
||||
</h4>
|
||||
{user.tags.includes('favorite') && (
|
||||
<FavoriteIcon svgClass={styles.svgIconFavorite} size="small" />
|
||||
)}
|
||||
{user.source && (
|
||||
<Link
|
||||
href={user.source}
|
||||
className={clsx(
|
||||
'button button--secondary button--sm',
|
||||
styles.showcaseCardSrcBtn,
|
||||
)}>
|
||||
<Translate id="showcase.card.sourceLink">source</Translate>
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
<p className={styles.showcaseCardBody}>{user.description}</p>
|
||||
</div>
|
||||
<ul className={clsx('card__footer', styles.cardFooter)}>
|
||||
<ShowcaseCardTag tags={user.tags} />
|
||||
</ul>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(ShowcaseCard);
|
|
@ -1,99 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
.showcaseCardImage {
|
||||
overflow: hidden;
|
||||
height: 150px;
|
||||
border-bottom: 2px solid var(--ifm-color-emphasis-200);
|
||||
}
|
||||
|
||||
.showcaseCardHeader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.showcaseCardTitle {
|
||||
margin-bottom: 0;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.showcaseCardTitle a {
|
||||
text-decoration: none;
|
||||
background: linear-gradient(
|
||||
var(--ifm-color-primary),
|
||||
var(--ifm-color-primary)
|
||||
)
|
||||
0% 100% / 0% 1px no-repeat;
|
||||
transition: background-size ease-out 200ms;
|
||||
}
|
||||
|
||||
.showcaseCardTitle a:not(:focus):hover {
|
||||
background-size: 100% 1px;
|
||||
}
|
||||
|
||||
.showcaseCardTitle,
|
||||
.showcaseCardHeader .svgIconFavorite {
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
.showcaseCardHeader .svgIconFavorite {
|
||||
color: var(--site-color-svg-icon-favorite);
|
||||
}
|
||||
|
||||
.showcaseCardSrcBtn {
|
||||
margin-left: 6px;
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.showcaseCardSrcBtn:focus-visible {
|
||||
background-color: var(--ifm-color-secondary-dark);
|
||||
}
|
||||
|
||||
[data-theme='dark'] .showcaseCardSrcBtn {
|
||||
background-color: var(--ifm-color-emphasis-200) !important;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .showcaseCardSrcBtn:hover {
|
||||
background-color: var(--ifm-color-emphasis-300) !important;
|
||||
}
|
||||
|
||||
.showcaseCardBody {
|
||||
font-size: smaller;
|
||||
line-height: 1.66;
|
||||
}
|
||||
|
||||
.cardFooter {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.tag {
|
||||
font-size: 0.675rem;
|
||||
border: 1px solid var(--ifm-color-secondary-darkest);
|
||||
cursor: default;
|
||||
margin-right: 6px;
|
||||
margin-bottom: 6px !important;
|
||||
border-radius: 12px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tag .textLabel {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.tag .colorLabel {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
margin-left: 6px;
|
||||
margin-right: 6px;
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {useState, useEffect, useCallback} from 'react';
|
||||
import {useHistory, useLocation} from '@docusaurus/router';
|
||||
|
||||
import {prepareUserState} from '../../index';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
import clsx from 'clsx';
|
||||
|
||||
export type Operator = 'OR' | 'AND';
|
||||
|
||||
export const OperatorQueryKey = 'operator';
|
||||
|
||||
export function readOperator(search: string): Operator {
|
||||
return (new URLSearchParams(search).get(OperatorQueryKey) ??
|
||||
'OR') as Operator;
|
||||
}
|
||||
|
||||
export default function ShowcaseFilterToggle(): JSX.Element {
|
||||
const id = 'showcase_filter_toggle';
|
||||
const location = useLocation();
|
||||
const history = useHistory();
|
||||
const [operator, setOperator] = useState(false);
|
||||
useEffect(() => {
|
||||
setOperator(readOperator(location.search) === 'AND');
|
||||
}, [location]);
|
||||
const toggleOperator = useCallback(() => {
|
||||
setOperator((o) => !o);
|
||||
const searchParams = new URLSearchParams(location.search);
|
||||
searchParams.delete(OperatorQueryKey);
|
||||
if (!operator) {
|
||||
searchParams.append(OperatorQueryKey, operator ? 'OR' : 'AND');
|
||||
}
|
||||
history.push({
|
||||
...location,
|
||||
search: searchParams.toString(),
|
||||
state: prepareUserState(),
|
||||
});
|
||||
}, [operator, location, history]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id={id}
|
||||
className="screen-reader-only"
|
||||
aria-label="Toggle between or and and for the tags you selected"
|
||||
onChange={toggleOperator}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
toggleOperator();
|
||||
}
|
||||
}}
|
||||
checked={operator}
|
||||
/>
|
||||
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
|
||||
<label htmlFor={id} className={clsx(styles.checkboxLabel, 'shadow--md')}>
|
||||
<span className={styles.checkboxLabelOr}>OR</span>
|
||||
<span className={styles.checkboxLabelAnd}>AND</span>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
.checkboxLabel {
|
||||
--height: 25px;
|
||||
--width: 80px;
|
||||
--border: 2px;
|
||||
display: flex;
|
||||
width: var(--width);
|
||||
height: var(--height);
|
||||
position: relative;
|
||||
border-radius: var(--height);
|
||||
border: var(--border) solid var(--ifm-color-primary-darkest);
|
||||
cursor: pointer;
|
||||
justify-content: space-around;
|
||||
opacity: 0.75;
|
||||
transition: opacity var(--ifm-transition-fast)
|
||||
var(--ifm-transition-timing-default);
|
||||
box-shadow: var(--ifm-global-shadow-md);
|
||||
}
|
||||
|
||||
.checkboxLabel:hover {
|
||||
opacity: 1;
|
||||
box-shadow: var(--ifm-global-shadow-md),
|
||||
0 0 2px 1px var(--ifm-color-primary-dark);
|
||||
}
|
||||
|
||||
.checkboxLabel::after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
inset: 0;
|
||||
width: calc(var(--width) / 2);
|
||||
height: 100%;
|
||||
border-radius: var(--height);
|
||||
background-color: var(--ifm-color-primary-darkest);
|
||||
transition: transform var(--ifm-transition-fast)
|
||||
var(--ifm-transition-timing-default);
|
||||
transform: translateX(calc(var(--width) / 2 - var(--border)));
|
||||
}
|
||||
|
||||
input:focus-visible ~ .checkboxLabel::after {
|
||||
outline: 2px solid currentColor;
|
||||
}
|
||||
|
||||
.checkboxLabel > * {
|
||||
font-size: 0.8rem;
|
||||
color: inherit;
|
||||
transition: opacity 150ms ease-in 50ms;
|
||||
}
|
||||
|
||||
input:checked ~ .checkboxLabel::after {
|
||||
transform: translateX(calc(-1 * var(--border)));
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {
|
||||
useCallback,
|
||||
useState,
|
||||
useEffect,
|
||||
type ComponentProps,
|
||||
type ReactNode,
|
||||
type ReactElement,
|
||||
} from 'react';
|
||||
import {useHistory, useLocation} from '@docusaurus/router';
|
||||
import {toggleListItem} from '@site/src/utils/jsUtils';
|
||||
import {prepareUserState} from '../../index';
|
||||
import {
|
||||
type TagType,
|
||||
} from '@site/src/data/tags';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
|
||||
interface Props extends ComponentProps<'input'> {
|
||||
icon: ReactElement<ComponentProps<'svg'>>;
|
||||
label: ReactNode;
|
||||
tag: TagType;
|
||||
}
|
||||
|
||||
const TagQueryStringKey = 'tags';
|
||||
|
||||
export function readSearchTags(search: string): TagType[] {
|
||||
return new URLSearchParams(search).getAll(TagQueryStringKey) as TagType[];
|
||||
}
|
||||
|
||||
function replaceSearchTags(search: string, newTags: TagType[]) {
|
||||
const searchParams = new URLSearchParams(search);
|
||||
searchParams.delete(TagQueryStringKey);
|
||||
newTags.forEach((tag) => searchParams.append(TagQueryStringKey, tag));
|
||||
return searchParams.toString();
|
||||
}
|
||||
|
||||
function ShowcaseTagSelect(
|
||||
{id, icon, label, tag, ...rest}: Props,
|
||||
ref: React.ForwardedRef<HTMLLabelElement>,
|
||||
) {
|
||||
const location = useLocation();
|
||||
const history = useHistory();
|
||||
const [selected, setSelected] = useState(false);
|
||||
useEffect(() => {
|
||||
const tags = readSearchTags(location.search);
|
||||
setSelected(tags.includes(tag));
|
||||
}, [tag, location]);
|
||||
const toggleTag = useCallback(() => {
|
||||
const tags = readSearchTags(location.search);
|
||||
const newTags = toggleListItem(tags, tag);
|
||||
const newSearch = replaceSearchTags(location.search, newTags);
|
||||
history.push({
|
||||
...location,
|
||||
search: newSearch,
|
||||
state: prepareUserState(),
|
||||
});
|
||||
}, [tag, location, history]);
|
||||
return (
|
||||
<>
|
||||
<input
|
||||
type="checkbox"
|
||||
id={id}
|
||||
className="screen-reader-only"
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
toggleTag();
|
||||
}
|
||||
}}
|
||||
onFocus={(e) => {
|
||||
if (e.relatedTarget) {
|
||||
e.target.nextElementSibling?.dispatchEvent(
|
||||
new KeyboardEvent('focus'),
|
||||
);
|
||||
}
|
||||
}}
|
||||
onBlur={(e) => {
|
||||
e.target.nextElementSibling?.dispatchEvent(new KeyboardEvent('blur'));
|
||||
}}
|
||||
onChange={toggleTag}
|
||||
checked={selected}
|
||||
{...rest}
|
||||
/>
|
||||
<label ref={ref} htmlFor={id} className={styles.checkboxLabel}>
|
||||
{label}
|
||||
{icon}
|
||||
</label>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.forwardRef(ShowcaseTagSelect);
|
|
@ -1,38 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
.checkboxLabel:hover {
|
||||
opacity: 1;
|
||||
box-shadow: 0 0 2px 1px var(--ifm-color-secondary-darkest);
|
||||
}
|
||||
|
||||
input[type='checkbox'] + .checkboxLabel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
line-height: 1.5;
|
||||
border-radius: 4px;
|
||||
padding: 0.275rem 0.8rem;
|
||||
opacity: 0.85;
|
||||
transition: opacity 200ms ease-out;
|
||||
border: 2px solid var(--ifm-color-secondary-darkest);
|
||||
}
|
||||
|
||||
input:focus-visible + .checkboxLabel {
|
||||
outline: 2px solid currentColor;
|
||||
}
|
||||
|
||||
input:checked + .checkboxLabel {
|
||||
opacity: 0.9;
|
||||
background-color: var(--site-color-checkbox-checked-bg);
|
||||
border: 2px solid var(--ifm-color-primary-darkest);
|
||||
}
|
||||
|
||||
input:checked + .checkboxLabel:hover {
|
||||
opacity: 0.75;
|
||||
box-shadow: 0 0 2px 1px var(--ifm-color-primary-dark);
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {useEffect, useState, useRef} from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import {usePopper} from 'react-popper';
|
||||
import styles from './styles.module.css';
|
||||
|
||||
interface Props {
|
||||
anchorEl?: HTMLElement | string;
|
||||
id: string;
|
||||
text: string;
|
||||
delay?: number;
|
||||
children: React.ReactElement;
|
||||
}
|
||||
|
||||
export default function Tooltip({
|
||||
children,
|
||||
id,
|
||||
anchorEl,
|
||||
text,
|
||||
delay,
|
||||
}: Props): JSX.Element {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [referenceElement, setReferenceElement] = useState<HTMLElement | null>(
|
||||
null,
|
||||
);
|
||||
const [popperElement, setPopperElement] = useState<HTMLElement | null>(null);
|
||||
const [arrowElement, setArrowElement] = useState<HTMLElement | null>(null);
|
||||
const [container, setContainer] = useState<Element | null>(null);
|
||||
const {styles: popperStyles, attributes} = usePopper(
|
||||
referenceElement,
|
||||
popperElement,
|
||||
{
|
||||
modifiers: [
|
||||
{
|
||||
name: 'arrow',
|
||||
options: {
|
||||
element: arrowElement,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: [0, 8],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
const timeout = useRef<number | null>(null);
|
||||
const tooltipId = `${id}_tooltip`;
|
||||
|
||||
useEffect(() => {
|
||||
if (anchorEl) {
|
||||
if (typeof anchorEl === 'string') {
|
||||
setContainer(document.querySelector(anchorEl));
|
||||
} else {
|
||||
setContainer(anchorEl);
|
||||
}
|
||||
} else {
|
||||
setContainer(document.body);
|
||||
}
|
||||
}, [container, anchorEl]);
|
||||
|
||||
useEffect(() => {
|
||||
const showEvents = ['mouseenter', 'focus'];
|
||||
const hideEvents = ['mouseleave', 'blur'];
|
||||
|
||||
const handleOpen = () => {
|
||||
// There is no point in displaying an empty tooltip.
|
||||
if (text === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the title ahead of time to avoid displaying
|
||||
// two tooltips at the same time (native + this one).
|
||||
referenceElement?.removeAttribute('title');
|
||||
|
||||
timeout.current = window.setTimeout(() => {
|
||||
setOpen(true);
|
||||
}, delay || 400);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
clearInterval(timeout.current!);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
if (referenceElement) {
|
||||
showEvents.forEach((event) => {
|
||||
referenceElement.addEventListener(event, handleOpen);
|
||||
});
|
||||
|
||||
hideEvents.forEach((event) => {
|
||||
referenceElement.addEventListener(event, handleClose);
|
||||
});
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (referenceElement) {
|
||||
showEvents.forEach((event) => {
|
||||
referenceElement.removeEventListener(event, handleOpen);
|
||||
});
|
||||
|
||||
hideEvents.forEach((event) => {
|
||||
referenceElement.removeEventListener(event, handleClose);
|
||||
});
|
||||
}
|
||||
};
|
||||
}, [referenceElement, text, delay]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{React.cloneElement(children, {
|
||||
ref: setReferenceElement,
|
||||
'aria-describedby': open ? tooltipId : undefined,
|
||||
})}
|
||||
{container
|
||||
? ReactDOM.createPortal(
|
||||
open && (
|
||||
<div
|
||||
id={tooltipId}
|
||||
role="tooltip"
|
||||
ref={setPopperElement}
|
||||
className={styles.tooltip}
|
||||
style={popperStyles.popper}
|
||||
{...attributes.popper}>
|
||||
{text}
|
||||
<span
|
||||
ref={setArrowElement}
|
||||
className={styles.tooltipArrow}
|
||||
style={popperStyles.arrow}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
container,
|
||||
)
|
||||
: container}
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
.tooltip {
|
||||
border-radius: 4px;
|
||||
padding: 4px 8px;
|
||||
color: var(--site-color-tooltip);
|
||||
background: var(--site-color-tooltip-background);
|
||||
font-size: 0.8rem;
|
||||
z-index: 500;
|
||||
line-height: 1.4;
|
||||
font-weight: 500;
|
||||
max-width: 300px;
|
||||
opacity: 0.92;
|
||||
}
|
||||
|
||||
.tooltipArrow {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.tooltipArrow,
|
||||
.tooltipArrow::before {
|
||||
position: absolute;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
.tooltipArrow::before {
|
||||
visibility: visible;
|
||||
content: '';
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.tooltip[data-popper-placement^='top'] > .tooltipArrow {
|
||||
bottom: -4px;
|
||||
}
|
||||
|
||||
.tooltip[data-popper-placement^='bottom'] > .tooltipArrow {
|
||||
top: -4px;
|
||||
}
|
|
@ -1,345 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {useState, useMemo, useEffect} from 'react';
|
||||
|
||||
import Layout from '@theme/Layout';
|
||||
import clsx from 'clsx';
|
||||
|
||||
import FavoriteIcon from '@site/src/components/svgIcons/FavoriteIcon';
|
||||
import ShowcaseTagSelect, {
|
||||
readSearchTags,
|
||||
} from './_components/ShowcaseTagSelect';
|
||||
import ShowcaseFilterToggle, {
|
||||
type Operator,
|
||||
readOperator,
|
||||
} from './_components/ShowcaseFilterToggle';
|
||||
import ShowcaseCard from './_components/ShowcaseCard';
|
||||
import {
|
||||
Tags,
|
||||
type User,
|
||||
type TagType,
|
||||
} from '@site/src/data/tags';
|
||||
import {
|
||||
sortedUsers,
|
||||
TagList,
|
||||
} from '@site/src/data/users';
|
||||
import ShowcaseTooltip from './_components/ShowcaseTooltip';
|
||||
|
||||
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
||||
import Translate, {translate} from '@docusaurus/Translate';
|
||||
import {useHistory, useLocation} from '@docusaurus/router';
|
||||
import {usePluralForm} from '@docusaurus/theme-common';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
|
||||
const TITLE = 'See Static Web Apps In Action';
|
||||
const DESCRIPTION = 'A community-contributed app showcase to learn from!';
|
||||
const EDIT_URL = 'https://github.com/microsoft/static-web-apps-gallery-code-samples/edit/master/docs/www/src/data/users.tsx'
|
||||
|
||||
/*
|
||||
'https://github.com/microsoft/static-web-apps-gallery-code-samples/edit/master/docs/www/src/data/users.tsx';
|
||||
*/
|
||||
|
||||
type UserState = {
|
||||
scrollTopPosition: number;
|
||||
focusedElementId: string | undefined;
|
||||
};
|
||||
|
||||
function restoreUserState(userState: UserState | null) {
|
||||
const {scrollTopPosition, focusedElementId} = userState ?? {
|
||||
scrollTopPosition: 0,
|
||||
focusedElementId: undefined,
|
||||
};
|
||||
// @ts-expect-error: if focusedElementId is undefined it returns null
|
||||
document.getElementById(focusedElementId)?.focus();
|
||||
window.scrollTo({top: scrollTopPosition});
|
||||
}
|
||||
|
||||
export function prepareUserState(): UserState | undefined {
|
||||
if (ExecutionEnvironment.canUseDOM) {
|
||||
return {
|
||||
scrollTopPosition: window.scrollY,
|
||||
focusedElementId: document.activeElement?.id,
|
||||
};
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const SearchNameQueryKey = 'name';
|
||||
|
||||
function readSearchName(search: string) {
|
||||
return new URLSearchParams(search).get(SearchNameQueryKey);
|
||||
}
|
||||
|
||||
function filterUsers(
|
||||
users: User[],
|
||||
selectedTags: TagType[],
|
||||
operator: Operator,
|
||||
searchName: string | null,
|
||||
) {
|
||||
if (searchName) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
users = users.filter((user) =>
|
||||
user.title.toLowerCase().includes(searchName.toLowerCase()),
|
||||
);
|
||||
}
|
||||
if (selectedTags.length === 0) {
|
||||
return users;
|
||||
}
|
||||
return users.filter((user) => {
|
||||
if (user.tags.length === 0) {
|
||||
return false;
|
||||
}
|
||||
if (operator === 'AND') {
|
||||
return selectedTags.every((tag) => user.tags.includes(tag));
|
||||
}
|
||||
return selectedTags.some((tag) => user.tags.includes(tag));
|
||||
});
|
||||
}
|
||||
|
||||
function useFilteredUsers() {
|
||||
const location = useLocation<UserState>();
|
||||
const [operator, setOperator] = useState<Operator>('OR');
|
||||
// On SSR / first mount (hydration) no tag is selected
|
||||
const [selectedTags, setSelectedTags] = useState<TagType[]>([]);
|
||||
const [searchName, setSearchName] = useState<string | null>(null);
|
||||
// Sync tags from QS to state (delayed on purpose to avoid SSR/Client
|
||||
// hydration mismatch)
|
||||
useEffect(() => {
|
||||
setSelectedTags(readSearchTags(location.search));
|
||||
setOperator(readOperator(location.search));
|
||||
setSearchName(readSearchName(location.search));
|
||||
restoreUserState(location.state);
|
||||
}, [location]);
|
||||
|
||||
return useMemo(
|
||||
() => filterUsers(sortedUsers, selectedTags, operator, searchName),
|
||||
[selectedTags, operator, searchName],
|
||||
);
|
||||
}
|
||||
|
||||
function ShowcaseHeader() {
|
||||
return (
|
||||
<section className="margin-top--lg margin-bottom--lg text--center">
|
||||
<h1>{TITLE}</h1>
|
||||
<p>{DESCRIPTION}</p>
|
||||
<a
|
||||
className="button button--primary"
|
||||
href={EDIT_URL}
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
<Translate id="showcase.header.button">
|
||||
Add Your Project! 🙏
|
||||
</Translate>
|
||||
</a>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function useSiteCountPlural() {
|
||||
const {selectMessage} = usePluralForm();
|
||||
return (sitesCount: number) =>
|
||||
selectMessage(
|
||||
sitesCount,
|
||||
translate(
|
||||
{
|
||||
id: 'showcase.filters.resultCount',
|
||||
description:
|
||||
'Pluralized label for the number of sites found on the showcase. Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',
|
||||
message: '1 site|{sitesCount} sites',
|
||||
},
|
||||
{sitesCount},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function ShowcaseFilters() {
|
||||
const filteredUsers = useFilteredUsers();
|
||||
const siteCountPlural = useSiteCountPlural();
|
||||
return (
|
||||
<section className="container margin-top--l margin-bottom--lg">
|
||||
<div className={clsx('margin-bottom--sm', styles.filterCheckbox)}>
|
||||
<div>
|
||||
<h2>
|
||||
<Translate id="showcase.filters.title">Filters</Translate>
|
||||
</h2>
|
||||
<span>{siteCountPlural(filteredUsers.length)}</span>
|
||||
</div>
|
||||
<ShowcaseFilterToggle />
|
||||
</div>
|
||||
<ul className={styles.checkboxList}>
|
||||
{TagList.map((tag, i) => {
|
||||
const {label, description, color} = Tags[tag];
|
||||
const id = `showcase_checkbox_id_${tag}`;
|
||||
|
||||
return (
|
||||
<li key={i} className={styles.checkboxListItem}>
|
||||
<ShowcaseTooltip
|
||||
id={id}
|
||||
text={description}
|
||||
anchorEl="#__docusaurus">
|
||||
<ShowcaseTagSelect
|
||||
tag={tag}
|
||||
id={id}
|
||||
label={label}
|
||||
icon={
|
||||
tag === 'favorite' ? (
|
||||
<FavoriteIcon svgClass={styles.svgIconFavoriteXs} />
|
||||
) : (
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: color,
|
||||
width: 10,
|
||||
height: 10,
|
||||
borderRadius: '50%',
|
||||
marginLeft: 8,
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
/>
|
||||
</ShowcaseTooltip>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
const favoriteUsers = sortedUsers.filter((user) =>
|
||||
user.tags.includes('favorite'),
|
||||
);
|
||||
const otherUsers = sortedUsers.filter(
|
||||
(user) => !user.tags.includes('favorite'),
|
||||
);
|
||||
|
||||
function SearchBar() {
|
||||
const history = useHistory();
|
||||
const location = useLocation();
|
||||
const [value, setValue] = useState<string | null>(null);
|
||||
useEffect(() => {
|
||||
setValue(readSearchName(location.search));
|
||||
}, [location]);
|
||||
return (
|
||||
<div className={styles.searchContainer}>
|
||||
<input
|
||||
id="searchbar"
|
||||
placeholder={translate({
|
||||
message: 'Search for site name...',
|
||||
id: 'showcase.searchBar.placeholder',
|
||||
})}
|
||||
value={value ?? undefined}
|
||||
onInput={(e) => {
|
||||
setValue(e.currentTarget.value);
|
||||
const newSearch = new URLSearchParams(location.search);
|
||||
newSearch.delete(SearchNameQueryKey);
|
||||
if (e.currentTarget.value) {
|
||||
newSearch.set(SearchNameQueryKey, e.currentTarget.value);
|
||||
}
|
||||
history.push({
|
||||
...location,
|
||||
search: newSearch.toString(),
|
||||
state: prepareUserState(),
|
||||
});
|
||||
setTimeout(() => {
|
||||
document.getElementById('searchbar')?.focus();
|
||||
}, 0);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ShowcaseCards() {
|
||||
const filteredUsers = useFilteredUsers();
|
||||
|
||||
if (filteredUsers.length === 0) {
|
||||
return (
|
||||
<section className="margin-top--lg margin-bottom--xl">
|
||||
<div className="container padding-vert--md text--center">
|
||||
<h2>
|
||||
<Translate id="showcase.usersList.noResult">
|
||||
Be the first to add an example project!
|
||||
</Translate>
|
||||
</h2>
|
||||
<SearchBar />
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="margin-top--lg margin-bottom--xl">
|
||||
{filteredUsers.length === sortedUsers.length ? (
|
||||
<>
|
||||
<div className={styles.showcaseFavorite}>
|
||||
<div className="container">
|
||||
<div
|
||||
className={clsx(
|
||||
'margin-bottom--md',
|
||||
styles.showcaseFavoriteHeader,
|
||||
)}>
|
||||
<h2>
|
||||
<Translate id="showcase.favoritesList.title">
|
||||
Our favorites
|
||||
</Translate>
|
||||
</h2>
|
||||
<FavoriteIcon svgClass={styles.svgIconFavorite} />
|
||||
<SearchBar />
|
||||
</div>
|
||||
<ul className={clsx('container', styles.showcaseList)}>
|
||||
{favoriteUsers.map((user) => (
|
||||
<ShowcaseCard key={user.title} user={user} />
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="container margin-top--lg">
|
||||
<h2 className={styles.showcaseHeader}>
|
||||
<Translate id="showcase.usersList.allUsers">All sites</Translate>
|
||||
</h2>
|
||||
<ul className={styles.showcaseList}>
|
||||
{otherUsers.map((user) => (
|
||||
<ShowcaseCard key={user.title} user={user} />
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="container">
|
||||
<div
|
||||
className={clsx(
|
||||
'margin-bottom--md',
|
||||
styles.showcaseFavoriteHeader,
|
||||
)}>
|
||||
<SearchBar />
|
||||
</div>
|
||||
<ul className={styles.showcaseList}>
|
||||
{filteredUsers.map((user) => (
|
||||
<ShowcaseCard key={user.title} user={user} />
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Showcase(): JSX.Element {
|
||||
return (
|
||||
<Layout title={TITLE} description={DESCRIPTION}>
|
||||
<main className="margin-vert--lg">
|
||||
<ShowcaseHeader />
|
||||
<ShowcaseFilters />
|
||||
<ShowcaseCards />
|
||||
</main>
|
||||
</Layout>
|
||||
);
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
.filterCheckbox {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.filterCheckbox,
|
||||
.checkboxList {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filterCheckbox > div:first-child {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filterCheckbox > div > * {
|
||||
margin-bottom: 0;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.checkboxList {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.checkboxList,
|
||||
.showcaseList {
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.checkboxListItem {
|
||||
user-select: none;
|
||||
white-space: nowrap;
|
||||
height: 32px;
|
||||
font-size: 0.8rem;
|
||||
margin-top: 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.checkboxListItem:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.searchContainer {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.searchContainer input {
|
||||
height: 30px;
|
||||
border-radius: 15px;
|
||||
padding: 10px;
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
.showcaseList {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.showcaseFavorite {
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
background-color: var(--site-color-favorite-background);
|
||||
}
|
||||
|
||||
.showcaseFavoriteHeader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.showcaseFavoriteHeader > h2 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.showcaseFavoriteHeader > svg {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.svgIconFavoriteXs,
|
||||
.svgIconFavorite {
|
||||
color: var(--site-color-svg-icon-favorite);
|
||||
}
|
||||
|
||||
.svgIconFavoriteXs {
|
||||
margin-left: 0.625rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.svgIconFavorite {
|
||||
margin-left: 1rem;
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
// Inspired by https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore#_sortby-and-_orderby
|
||||
export function sortBy<T>(
|
||||
array: T[],
|
||||
getter: (item: T) => string | number | boolean,
|
||||
): T[] {
|
||||
const sortedArray = [...array];
|
||||
sortedArray.sort((a, b) =>
|
||||
// eslint-disable-next-line no-nested-ternary
|
||||
getter(a) > getter(b) ? 1 : getter(b) > getter(a) ? -1 : 0,
|
||||
);
|
||||
return sortedArray;
|
||||
}
|
||||
|
||||
export function toggleListItem<T>(list: T[], item: T): T[] {
|
||||
const itemIndex = list.indexOf(item);
|
||||
if (itemIndex === -1) {
|
||||
return list.concat(item);
|
||||
}
|
||||
const newList = [...list];
|
||||
newList.splice(itemIndex, 1);
|
||||
return newList;
|
||||
}
|
Двоичные данные
docs/www/static/img/docusaurus.png
До Ширина: | Высота: | Размер: 5.0 KiB |
Двоичные данные
docs/www/static/img/favicon.ico
До Ширина: | Высота: | Размер: 3.5 KiB |
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 250 250" style="enable-background:new 0 0 250 250;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#DD0031;}
|
||||
.st1{fill:#C3002F;}
|
||||
.st2{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<polygon class="st0" points="125,30 125,30 125,30 31.9,63.2 46.1,186.3 125,230 125,230 125,230 203.9,186.3 218.1,63.2 "/>
|
||||
<polygon class="st1" points="125,30 125,52.2 125,52.1 125,153.4 125,153.4 125,230 125,230 203.9,186.3 218.1,63.2 125,30 "/>
|
||||
<path class="st2" d="M125,52.1L66.8,182.6h0h21.7h0l11.7-29.2h49.4l11.7,29.2h0h21.7h0L125,52.1L125,52.1L125,52.1L125,52.1
|
||||
L125,52.1z M142,135.4H108l17-40.9L142,135.4z"/>
|
||||
</g>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 899 B |
|
@ -1,23 +0,0 @@
|
|||
<svg width="150" height="150" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="e399c19f-b68f-429d-b176-18c2117ff73c" x1="-1032.172" x2="-1059.213" y1="145.312" y2="65.426" gradientTransform="matrix(1 0 0 -1 1075 158)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#114a8b"/>
|
||||
<stop offset="1" stop-color="#0669bc"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="ac2a6fc2-ca48-4327-9a3c-d4dcc3256e15" x1="-1023.725" x2="-1029.98" y1="108.083" y2="105.968" gradientTransform="matrix(1 0 0 -1 1075 158)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-opacity=".3"/>
|
||||
<stop offset=".071" stop-opacity=".2"/>
|
||||
<stop offset=".321" stop-opacity=".1"/>
|
||||
<stop offset=".623" stop-opacity=".05"/>
|
||||
<stop offset="1" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="a7fee970-a784-4bb1-af8d-63d18e5f7db9" x1="-1027.165" x2="-997.482" y1="147.642" y2="68.561" gradientTransform="matrix(1 0 0 -1 1075 158)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#3ccbf4"/>
|
||||
<stop offset="1" stop-color="#2892df"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path fill="url(#e399c19f-b68f-429d-b176-18c2117ff73c)" d="M33.338 6.544h26.038l-27.03 80.087a4.152 4.152 0 0 1-3.933 2.824H8.149a4.145 4.145 0 0 1-3.928-5.47L29.404 9.368a4.152 4.152 0 0 1 3.934-2.825z"/>
|
||||
<path fill="#0078d4" d="M71.175 60.261h-41.29a1.911 1.911 0 0 0-1.305 3.309l26.532 24.764a4.171 4.171 0 0 0 2.846 1.121h23.38z"/>
|
||||
<path fill="url(#ac2a6fc2-ca48-4327-9a3c-d4dcc3256e15)" d="M33.338 6.544a4.118 4.118 0 0 0-3.943 2.879L4.252 83.917a4.14 4.14 0 0 0 3.908 5.538h20.787a4.443 4.443 0 0 0 3.41-2.9l5.014-14.777 17.91 16.705a4.237 4.237 0 0 0 2.666.972H81.24L71.024 60.261l-29.781.007L59.47 6.544z"/>
|
||||
<path fill="url(#a7fee970-a784-4bb1-af8d-63d18e5f7db9)" d="M66.595 9.364a4.145 4.145 0 0 0-3.928-2.82H33.648a4.146 4.146 0 0 1 3.928 2.82l25.184 74.62a4.146 4.146 0 0 1-3.928 5.472h29.02a4.146 4.146 0 0 0 3.927-5.472z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 2.1 KiB |
|
@ -1,8 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 106 28" focusable="false">
|
||||
<title>
|
||||
Gatsby
|
||||
</title>
|
||||
<path d="M62.9 12h2.8v10h-2.8v-1.3c-1 1.5-2.3 1.6-3.1 1.6-3.1 0-5.1-2.4-5.1-5.3 0-3 2-5.3 4.9-5.3.8 0 2.3.1 3.2 1.6V12zm-5.2 5c0 1.6 1.1 2.8 2.8 2.8 1.6 0 2.8-1.2 2.8-2.8 0-1.6-1.1-2.8-2.8-2.8-1.6 0-2.8 1.2-2.8 2.8zm13.5-2.6V22h-2.8v-7.6h-1.1V12h1.1V8.6h2.8V12h1.9v2.4h-1.9zm8.5 0c-.7-.6-1.3-.7-1.6-.7-.7 0-1.1.3-1.1.8 0 .3.1.6.9.9l.7.2c.8.3 2 .6 2.5 1.4.3.4.5 1 .5 1.7 0 .9-.3 1.8-1.1 2.5s-1.8 1.1-3 1.1c-2.1 0-3.2-1-3.9-1.7l1.5-1.7c.6.6 1.4 1.2 2.2 1.2.8 0 1.4-.4 1.4-1.1 0-.6-.5-.9-.9-1l-.6-.2c-.7-.3-1.5-.6-2.1-1.2-.5-.5-.8-1.1-.8-1.9 0-1 .5-1.8 1-2.3.8-.6 1.8-.7 2.6-.7.7 0 1.9.1 3.2 1.1l-1.4 1.6zm6.1-1.1c1-1.4 2.4-1.6 3.2-1.6 2.9 0 4.9 2.3 4.9 5.3s-2 5.3-5 5.3c-.6 0-2.1-.1-3.2-1.6V22H83V5.2h2.8v8.1zm-.3 3.7c0 1.6 1.1 2.8 2.8 2.8 1.6 0 2.8-1.2 2.8-2.8 0-1.6-1.1-2.8-2.8-2.8-1.7 0-2.8 1.2-2.8 2.8zm13 3.5L93.7 12H97l3.1 5.7 2.8-5.7h3.2l-8 15.3h-3.2l3.6-6.8zM54 13.7h-7v2.8h3.7c-.6 1.9-2 3.2-4.6 3.2-2.9 0-5-2.4-5-5.3S43.1 9 46 9c1.6 0 3.2.8 4.2 2.1l2.3-1.5C51 7.5 48.6 6.3 46 6.3c-4.4 0-8 3.6-8 8.1s3.4 8.1 8 8.1 8-3.6 8-8.1c.1-.3 0-.5 0-.7z"/>
|
||||
<path fill="#fff" d="M25 14h-7v2h4.8c-.7 3-2.9 5.5-5.8 6.5L5.5 11c1.2-3.5 4.6-6 8.5-6 3 0 5.7 1.5 7.4 3.8l1.5-1.3C20.9 4.8 17.7 3 14 3 8.8 3 4.4 6.7 3.3 11.6l13.2 13.2C21.3 23.6 25 19.2 25 14zm-22 .1c0 2.8 1.1 5.5 3.2 7.6 2.1 2.1 4.9 3.2 7.6 3.2L3 14.1z"/>
|
||||
<path d="M14 0C6.3 0 0 6.3 0 14s6.3 14 14 14 14-6.3 14-14S21.7 0 14 0zM6.2 21.8C4.1 19.7 3 16.9 3 14.2L13.9 25c-2.8-.1-5.6-1.1-7.7-3.2zm10.2 2.9L3.3 11.6C4.4 6.7 8.8 3 14 3c3.7 0 6.9 1.8 8.9 4.5l-1.5 1.3C19.7 6.5 17 5 14 5c-3.9 0-7.2 2.5-8.5 6L17 22.5c2.9-1 5.1-3.5 5.8-6.5H18v-2h7c0 5.2-3.7 9.6-8.6 10.7z" fill="#639"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 1.7 KiB |
До Ширина: | Высота: | Размер: 111 KiB |