diff --git a/.github/workflows/admin-sample.cd.yml b/.github/workflows/admin-sample.cd.yml index 20c90a0b1e..60dbe0e9d2 100644 --- a/.github/workflows/admin-sample.cd.yml +++ b/.github/workflows/admin-sample.cd.yml @@ -35,7 +35,7 @@ jobs: cd src/Templates/Boilerplate && dotnet build -c Release dotnet pack -c Release -o . -p:ReleaseVersion=0.0.0 -p:PackageVersion=0.0.0 dotnet new install Bit.Boilerplate.0.0.0.nupkg - cd ../../../ && dotnet new bit-bp --name AdminPanel --database PostgreSQL --sample Admin --appInsights --sentry --serverUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --signalR --framework net9.0 + cd ../../../ && dotnet new bit-bp --name AdminPanel --database PostgreSQL --sample Admin --appInsights --sentry --apiServerUrl ${{ env.SERVER_ADDRESS }} --webAppUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --signalR --framework net9.0 - name: Update core appsettings.json uses: devops-actions/variable-substitution@v1.2 @@ -88,7 +88,7 @@ jobs: cd src/Templates/Boilerplate && dotnet build -c Release dotnet pack -c Release -o . -p:ReleaseVersion=0.0.0 -p:PackageVersion=0.0.0 dotnet new install Bit.Boilerplate.0.0.0.nupkg - cd ../../../ && dotnet new bit-bp --name AdminPanel --database PostgreSQL --sample Admin --appInsights --sentry --serverUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --signalR --framework net9.0 + cd ../../../ && dotnet new bit-bp --name AdminPanel --database PostgreSQL --sample Admin --appInsights --sentry --apiServerUrl ${{ env.SERVER_ADDRESS }} --webAppUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --signalR --framework net9.0 - name: Update core appsettings.json uses: devops-actions/variable-substitution@v1.2 @@ -186,13 +186,14 @@ jobs: cd src\Templates\Boilerplate && dotnet build -c Release dotnet pack -c Release -o . -p:ReleaseVersion=0.0.0 -p:PackageVersion=0.0.0 dotnet new install Bit.Boilerplate.0.0.0.nupkg - cd ..\..\..\ && dotnet new bit-bp --name AdminPanel --database PostgreSQL --sample Admin --windows --appInsights --sentry --serverUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --captcha reCaptcha --signalR --offlineDb --framework net9.0 + cd ..\..\..\ && dotnet new bit-bp --name AdminPanel --database PostgreSQL --sample Admin --windows --appInsights --sentry --apiServerUrl ${{ env.SERVER_ADDRESS }} --webAppUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --captcha reCaptcha --signalR --framework net9.0 - name: Update core appsettings.json uses: devops-actions/variable-substitution@v1.2 with: files: 'AdminPanel\src\Shared\appsettings.json, AdminPanel\src\Client\AdminPanel.Client.Core\appsettings.json, AdminPanel\src\Client\AdminPanel.Client.Windows\appsettings.json' env: + WebAppUrl: ${{ env.SERVER_ADDRESS }} ServerAddress: ${{ env.SERVER_ADDRESS }} Logging.Sentry.Dsn: ${{ secrets.ADMINPANEL_SENTRY_DSN }} GoogleRecaptchaSiteKey: ${{ secrets.GOOGLE_RECAPTCHA_SITE_KEY }} @@ -234,7 +235,7 @@ jobs: cd src/Templates/Boilerplate && dotnet build -c Release dotnet pack -c Release -o . -p:ReleaseVersion=0.0.0 -p:PackageVersion=0.0.0 dotnet new install Bit.Boilerplate.0.0.0.nupkg - cd ../../../ && dotnet new bit-bp --name AdminPanel --database PostgreSQL --sample Admin --appInsights --sentry --serverUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --signalR --framework net9.0 + cd ../../../ && dotnet new bit-bp --name AdminPanel --database PostgreSQL --sample Admin --appInsights --sentry --apiServerUrl ${{ env.SERVER_ADDRESS }} --webAppUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --signalR --framework net9.0 - uses: actions/setup-node@v4 with: @@ -259,6 +260,7 @@ jobs: with: files: 'AdminPanel/src/Shared/appsettings.json, AdminPanel/src/Client/AdminPanel.Client.Core/appsettings.json, AdminPanel/src/Client/AdminPanel.Client.Maui/appsettings.json' env: + WebAppUrl: ${{ env.SERVER_ADDRESS }} ServerAddress: ${{ env.SERVER_ADDRESS }} Logging.Sentry.Dsn: ${{ secrets.ADMINPANEL_SENTRY_DSN }} GoogleRecaptchaSiteKey: ${{ secrets.GOOGLE_RECAPTCHA_SITE_KEY }} @@ -311,13 +313,14 @@ jobs: cd src/Templates/Boilerplate && dotnet build -c Release dotnet pack -c Release -o . -p:ReleaseVersion=0.0.0 -p:PackageVersion=0.0.0 dotnet new install Bit.Boilerplate.0.0.0.nupkg - cd ../../../ && dotnet new bit-bp --name AdminPanel --database PostgreSQL --sample Admin --appInsights --sentry --serverUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --signalR --framework net9.0 + cd ../../../ && dotnet new bit-bp --name AdminPanel --database PostgreSQL --sample Admin --appInsights --sentry --apiServerUrl ${{ env.SERVER_ADDRESS }} --webAppUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --signalR --framework net9.0 - name: Update core appsettings.json uses: devops-actions/variable-substitution@v1.2 with: files: 'AdminPanel/src/Shared/appsettings.json, AdminPanel/src/Client/AdminPanel.Client.Core/appsettings.json, AdminPanel/src/Client/AdminPanel.Client.Maui/appsettings.json' env: + WebAppUrl: ${{ env.SERVER_ADDRESS }} ServerAddress: ${{ env.SERVER_ADDRESS }} Logging.Sentry.Dsn: ${{ secrets.ADMINPANEL_SENTRY_DSN }} GoogleRecaptchaSiteKey: ${{ secrets.GOOGLE_RECAPTCHA_SITE_KEY }} diff --git a/.github/workflows/bit.full.ci.yml b/.github/workflows/bit.full.ci.yml index 003f326ba4..bb30fe241c 100644 --- a/.github/workflows/bit.full.ci.yml +++ b/.github/workflows/bit.full.ci.yml @@ -146,33 +146,33 @@ jobs: continue-on-error: true run: | dotnet new bit-bp --name TestPostgreSQL --database PostgreSQL --framework net8.0 --signalR - cd TestPostgreSQL/src/Server/TestPostgreSQL.Server.Api/ + cd TestPostgreSQL/src/Server/TestPostgreSQL.Server.Web/ dotnet build cd ../../../../ dotnet new bit-bp --name TestMySql --database MySql --framework net8.0 --sample Admin --offlineDb - cd TestMySql/src/Server/TestMySql.Server.Api/ + cd TestMySql/src/Server/TestMySql.Server.Web/ dotnet build cd ../../../../ dotnet new bit-bp --name TestOther --database Other --framework net9.0 --sample Todo --sentry - cd TestOther/src/Server/TestOther.Server.Api/ + cd TestOther/src/Server/TestOther.Server.Web/ dotnet build - name: Test file storage options continue-on-error: true run: | dotnet new bit-bp --name TestLocal --filesStorage Local --framework net8.0 --appInsights - cd TestLocal/src/Server/TestLocal.Server.Api/ + cd TestLocal/src/Server/TestLocal.Server.Web/ dotnet build cd ../../../../ dotnet new bit-bp --name TestAzureBlobStorage --filesStorage AzureBlobStorage --framework net9.0 --captcha reCaptcha --notification - cd TestAzureBlobStorage/src/Server/TestAzureBlobStorage.Server.Api/ + cd TestAzureBlobStorage/src/Server/TestAzureBlobStorage.Server.Web/ dotnet build - name: Test backend setup options continue-on-error: true run: | dotnet new bit-bp --name TestStandalone --api Standalone --framework net8.0 - cd TestStandalone/src/Server/TestStandalone.Server.Api/ + cd TestStandalone/src/Server/TestStandalone.Server.Web/ dotnet build cd ../ cd TestStandalone.Server.Web/ diff --git a/.github/workflows/todo-sample.cd.yml b/.github/workflows/todo-sample.cd.yml index b668a00726..ee7043d191 100644 --- a/.github/workflows/todo-sample.cd.yml +++ b/.github/workflows/todo-sample.cd.yml @@ -42,7 +42,7 @@ jobs: cd src/Templates/Boilerplate && dotnet build -c Release dotnet pack -c Release -o . -p:ReleaseVersion=0.0.0 -p:PackageVersion=0.0.0 dotnet new install Bit.Boilerplate.0.0.0.nupkg - cd ../../../ && dotnet new bit-bp --name TodoSample --database PostgreSQL --sample Todo --appInsights --sentry --serverUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --signalR --framework net8.0 + cd ../../../ && dotnet new bit-bp --name TodoSample --database PostgreSQL --sample Todo --appInsights --sentry --apiServerUrl ${{ env.SERVER_ADDRESS }} --webAppUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --signalR --framework net8.0 - name: Update core appsettings.json uses: devops-actions/variable-substitution@v1.2 @@ -121,8 +121,8 @@ jobs: CLOUDFLARE_ZONE: ${{ secrets.BITPLATFORM_DEV_CLOUDFLARE_ZONE }} CLOUDFLARE_TOKEN: ${{ secrets.CLOUDFLARE_TOKEN }} - deploy_blazor_wasm_standalone: - name: build blazor wasm standalone + deploy_blazor_wasm_standalone_aot: + name: build blazor wasm standalone (AOT) runs-on: ubuntu-24.04 steps: @@ -140,7 +140,7 @@ jobs: cd src/Templates/Boilerplate && dotnet build -c Release dotnet pack -c Release -o . -p:ReleaseVersion=0.0.0 -p:PackageVersion=0.0.0 dotnet new install Bit.Boilerplate.0.0.0.nupkg - cd ../../../ && dotnet new bit-bp --name TodoSample --database PostgreSQL --sample Todo --serverUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --framework net9.0 + cd ../../../ && dotnet new bit-bp --name TodoSample --database PostgreSQL --sample Todo --apiServerUrl ${{ env.SERVER_ADDRESS }} --webAppUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --framework net9.0 - name: Update core appsettings.json uses: devops-actions/variable-substitution@v1.2 @@ -166,7 +166,101 @@ jobs: - name: Upload to asw run: | npm install -g @azure/static-web-apps-cli - swa deploy --deployment-token ${{ secrets.TODO_ASW_TOKEN }} --env production --app-location ${{env.DOTNET_ROOT}}/client/wwwroot + swa deploy --deployment-token ${{ secrets.TODO_AOT_ASW_TOKEN }} --env production --app-location ${{env.DOTNET_ROOT}}/client/wwwroot + + deploy_blazor_wasm_standalone_offlineDb: + name: build blazor wasm standalone (Offline database) + runs-on: ubuntu-24.04 + + steps: + + - name: Checkout source code + uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + global-json-file: src/global.json + + - name: Create project from Boilerplate + run: | + cd src/Templates/Boilerplate && dotnet build -c Release + dotnet pack -c Release -o . -p:ReleaseVersion=0.0.0 -p:PackageVersion=0.0.0 + dotnet new install Bit.Boilerplate.0.0.0.nupkg + cd ../../../ && dotnet new bit-bp --name TodoSample --database PostgreSQL --sample Todo --appInsights --sentry --apiServerUrl ${{ env.SERVER_ADDRESS }} --webAppUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --offlineDb --signalR --framework net9.0 + + - name: Update core appsettings.json + uses: devops-actions/variable-substitution@v1.2 + with: + files: 'TodoSample/src/Shared/appsettings.json, TodoSample/src/Client/TodoSample.Client.Core/appsettings.json, TodoSample/src/Client/TodoSample.Client.Web/appsettings.json, TodoSample/src/Client/TodoSample.Client.Web/appsettings.Production.json' + env: + ServerAddress: ${{ env.SERVER_ADDRESS }} + GoogleRecaptchaSiteKey: ${{ secrets.GOOGLE_RECAPTCHA_SITE_KEY }} + + - uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Install wasm + run: cd src && dotnet workload install wasm-tools + + - name: Generate CSS/JS files + run: dotnet build TodoSample/src/Client/TodoSample.Client.Core/TodoSample.Client.Core.csproj -t:BeforeBuildTasks -p:Version="${{ vars.APPLICATION_DISPLAY_VERSION}}" --no-restore -c Release + + - name: Publish + run: dotnet publish TodoSample/src/Client/TodoSample.Client.Web/TodoSample.Client.Web.csproj -c Release -p:PwaEnabled=true -o ${{env.DOTNET_ROOT}}/client -p:Version="${{ vars.APPLICATION_DISPLAY_VERSION}}" + + - name: Upload to asw + run: | + npm install -g @azure/static-web-apps-cli + swa deploy --deployment-token ${{ secrets.TODO_OFFLINE_ASW_TOKEN }} --env production --app-location ${{env.DOTNET_ROOT}}/client/wwwroot + + deploy_blazor_wasm_standalone_small: + name: build blazor wasm standalone (small) + runs-on: ubuntu-24.04 + + steps: + + - name: Checkout source code + uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + global-json-file: src/global.json + + - name: Create project from Boilerplate + run: | + cd src/Templates/Boilerplate && dotnet build -c Release + dotnet pack -c Release -o . -p:ReleaseVersion=0.0.0 -p:PackageVersion=0.0.0 + dotnet new install Bit.Boilerplate.0.0.0.nupkg + cd ../../../ && dotnet new bit-bp --name TodoSample --database PostgreSQL --sample Todo --apiServerUrl ${{ env.SERVER_ADDRESS }} --webAppUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --framework net9.0 + + - name: Update core appsettings.json + uses: devops-actions/variable-substitution@v1.2 + with: + files: 'TodoSample/src/Shared/appsettings.json, TodoSample/src/Client/TodoSample.Client.Core/appsettings.json, TodoSample/src/Client/TodoSample.Client.Web/appsettings.json, TodoSample/src/Client/TodoSample.Client.Web/appsettings.Production.json' + env: + ServerAddress: ${{ env.SERVER_ADDRESS }} + GoogleRecaptchaSiteKey: ${{ secrets.GOOGLE_RECAPTCHA_SITE_KEY }} + + - uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Install wasm + run: cd src && dotnet workload install wasm-tools + + - name: Generate CSS/JS files + run: dotnet build TodoSample/src/Client/TodoSample.Client.Core/TodoSample.Client.Core.csproj -t:BeforeBuildTasks -p:Version="${{ vars.APPLICATION_DISPLAY_VERSION}}" --no-restore -c Release + + - name: Publish + run: dotnet publish TodoSample/src/Client/TodoSample.Client.Web/TodoSample.Client.Web.csproj -c Release -p:PwaEnabled=true -o ${{env.DOTNET_ROOT}}/client -p:Version="${{ vars.APPLICATION_DISPLAY_VERSION}}" -p:MultilingualEnabled=false + + - name: Upload to asw + run: | + npm install -g @azure/static-web-apps-cli + swa deploy --deployment-token ${{ secrets.TODO_SMALL_ASW_TOKEN }} --env production --app-location ${{env.DOTNET_ROOT}}/client/wwwroot build_blazor_hybrid_windows: name: build blazor hybrid (windows) @@ -195,13 +289,14 @@ jobs: cd src\Templates\Boilerplate && dotnet build -c Release dotnet pack -c Release -o . -p:ReleaseVersion=0.0.0 -p:PackageVersion=0.0.0 dotnet new install Bit.Boilerplate.0.0.0.nupkg - cd ..\..\..\ && dotnet new bit-bp --name TodoSample --database PostgreSQL --sample Todo --windows --appInsights --sentry --serverUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --captcha reCaptcha --signalR --framework net8.0 + cd ..\..\..\ && dotnet new bit-bp --name TodoSample --database PostgreSQL --sample Todo --windows --appInsights --sentry --apiServerUrl ${{ env.SERVER_ADDRESS }} --webAppUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --captcha reCaptcha --signalR --framework net8.0 - name: Update core appsettings.json uses: devops-actions/variable-substitution@v1.2 with: files: 'TodoSample\src\Shared\appsettings.json, TodoSample\src\Client\TodoSample.Client.Core\appsettings.json, TodoSample\src\Client\TodoSample.Client.Windows\appsettings.json' env: + WebAppUrl: ${{ env.SERVER_ADDRESS }} ServerAddress: ${{ env.SERVER_ADDRESS }} Logging.Sentry.Dsn: ${{ secrets.TODO_SENTRY_DSN }} WindowsUpdate.FilesUrl: https://windows-todo.bitplatform.dev @@ -251,7 +346,7 @@ jobs: cd src/Templates/Boilerplate && dotnet build -c Release dotnet pack -c Release -o . -p:ReleaseVersion=0.0.0 -p:PackageVersion=0.0.0 dotnet new install Bit.Boilerplate.0.0.0.nupkg - cd ../../../ && dotnet new bit-bp --name TodoSample --database PostgreSQL --sample Todo --appInsights --sentry --serverUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --signalR --framework net8.0 + cd ../../../ && dotnet new bit-bp --name TodoSample --database PostgreSQL --sample Todo --appInsights --sentry --apiServerUrl ${{ env.SERVER_ADDRESS }} --webAppUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --signalR --framework net8.0 - name: Extract Android signing key from env uses: timheuer/base64-to-file@v1.2 @@ -272,6 +367,7 @@ jobs: with: files: 'TodoSample/src/Shared/appsettings.json, TodoSample/src/Client/TodoSample.Client.Core/appsettings.json, TodoSample/src/Client/TodoSample.Client.Maui/appsettings.json' env: + WebAppUrl: ${{ env.SERVER_ADDRESS }} ServerAddress: ${{ env.SERVER_ADDRESS }} Logging.Sentry.Dsn: ${{ secrets.TODO_SENTRY_DSN }} GoogleRecaptchaSiteKey: ${{ secrets.GOOGLE_RECAPTCHA_SITE_KEY }} @@ -348,13 +444,14 @@ jobs: cd src/Templates/Boilerplate && dotnet build -c Release dotnet pack -c Release -o . -p:ReleaseVersion=0.0.0 -p:PackageVersion=0.0.0 dotnet new install Bit.Boilerplate.0.0.0.nupkg - cd ../../../ && dotnet new bit-bp --name TodoSample --database PostgreSQL --sample Todo --appInsights --sentry --serverUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --signalR --framework net8.0 + cd ../../../ && dotnet new bit-bp --name TodoSample --database PostgreSQL --sample Todo --appInsights --sentry --apiServerUrl ${{ env.SERVER_ADDRESS }} --webAppUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --signalR --framework net8.0 - name: Update core appsettings.json uses: devops-actions/variable-substitution@v1.2 with: files: 'TodoSample/src/Shared/appsettings.json, TodoSample/src/Client/TodoSample.Client.Core/appsettings.json, TodoSample/src/Client/TodoSample.Client.Maui/appsettings.json' env: + WebAppUrl: ${{ env.SERVER_ADDRESS }} ServerAddress: ${{ env.SERVER_ADDRESS }} Logging.Sentry.Dsn: ${{ secrets.TODO_SENTRY_DSN }} GoogleRecaptchaSiteKey: ${{ secrets.GOOGLE_RECAPTCHA_SITE_KEY }} diff --git a/LICENSE b/LICENSE index 8ab0dda5ec..0ab084ff9e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 bit platform +Copyright (c) 2025 bit platform Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index e6111238e8..f57456a326 100644 --- a/README.md +++ b/README.md @@ -44,12 +44,14 @@ The following apps are our open-source projects powered by the bit platform show | AdminPanel | [![Prerendered PWA](https://github-production-user-asset-6210df.s3.amazonaws.com/6169846/251381583-8b8eb895-80c9-4811-9641-57a5a08db163.png)](https://adminpanel.bitplatform.dev) | [![iOS app](https://github-production-user-asset-6210df.s3.amazonaws.com/6169846/251381842-e72976ce-fd20-431d-a677-ca1ed625b83b.png)](https://apps.apple.com/us/app/bit-adminpanel/id6450611349) | [![Android app](https://github-production-user-asset-6210df.s3.amazonaws.com/6169846/251381958-24931682-87f6-44fc-a1c7-eecf46387005.png)](https://play.google.com/store/apps/details?id=com.bitplatform.AdminPanel.Template) | [![Windows app](https://github-production-user-asset-6210df.s3.amazonaws.com/6169846/251382080-9ae97fea-934c-4097-aca4-124a2aed1595.png)](https://windows-admin.bitplatform.dev/AdminPanel.Client.Windows-win-Setup.exe) | [![macOS app](https://github-production-user-asset-6210df.s3.amazonaws.com/6169846/251382211-0d58f9ba-1a1f-4481-a0ca-b23a393cca9f.png)](https://apps.apple.com/nl/app/bit-adminpanel/id6450611349) | | bitplatform | [![SPA](https://github-production-user-asset-6210df.s3.amazonaws.com/6169846/251395129-71a5a79c-af74-4d4e-a0f7-ed9a15cf2e46.png)](https://bitplatform.dev)| -1. [bitplatform.dev](https://bitplatform.dev): .NET 9 Pre-rendered SPA with Blazor WebAssembly -2. [blazorui.bitplatform.dev](https://blazorui.bitplatform.dev): .NET 9 Pre-rendered PWA with Blazor WebAssembly -3. [todo.bitplatform.dev](https://todo.bitplatform.dev): .NET 8 Pre-rendered PWA with Blazor WebAssembly -5. [adminpanel.bitplatform.dev](https://adminpanel.bitplatform.dev): .NET 9 PWA with Blazor WebAssembly -6. [adminpanel.bitplatform.cc](https://adminpanel.bitplatform.cc): .NET 9 PWA with Blazor WebAssembly Standalone (Free Azure static web app) -7. [todo.bitplatform.cc](https://todo.bitplatform.cc): AOT Compiled .NET 9 PWA with Blazor WebAssembly Standalone (Free Azure static web app) +1. [bitplatform.dev](https://bitplatform.dev): .NET 9 Pre-rendered SPA with Blazor WebAssembly (Azure Web App + Cloudflare CDN) +2. [blazorui.bitplatform.dev](https://blazorui.bitplatform.dev): .NET 9 Pre-rendered PWA with Blazor WebAssembly (Azure Web App + Cloudflare CDN) +3. [todo.bitplatform.dev](https://todo.bitplatform.dev): .NET 8 Pre-rendered PWA with Blazor WebAssembly (Azure Web App + Cloudflare CDN) +5. [adminpanel.bitplatform.dev](https://adminpanel.bitplatform.dev): .NET 9 PWA with Blazor WebAssembly (Azure Web App + Cloudflare CDN) +6. [adminpanel.bitplatform.cc](https://adminpanel.bitplatform.cc): .NET 9 PWA with Blazor WebAssembly Standalone (Azure static web app) +7. [todo-aot.bitplatform.cc](https://todo-aot.bitplatform.cc): .NET 9 AOT Compiled PWA with Blazor WebAssembly Standalone (Azure static web app) +8. [todo-small.bitplatform.cc](https://todo-small.bitplatform.cc): .NET 9 Todo demo app with smaller download footprint (Azure static web app) +9. [todo-offline.bitplatform.cc](https://todo-offline.bitplatform.cc): .NET 9 Todo demo app with ef-core & sqlite (Azure static web app) [Todo](https://todo.bitplatform.dev) & [Adminpanel](https://adminpanel.bitplatform.dev) web apps will launch their respective Android and iOS applications if you have already installed them, mirroring the behavior of apps like YouTube and Instagram. diff --git a/src/Besql/Bit.Besql/wwwroot/bit-besql.js b/src/Besql/Bit.Besql/wwwroot/bit-besql.js index a7229e8651..5ad9782aea 100644 --- a/src/Besql/Bit.Besql/wwwroot/bit-besql.js +++ b/src/Besql/Bit.Besql/wwwroot/bit-besql.js @@ -1,5 +1,5 @@ var BitBesql = window.BitBesql || {}; -BitBesql.version = window['bit-besql version'] = '9.1.2'; +BitBesql.version = window['bit-besql version'] = '9.2.0'; BitBesql.init = async function init(fileName) { const sqliteFilePath = `/${fileName}`; diff --git a/src/Bit.Build.props b/src/Bit.Build.props index 29ac825be1..c690155096 100644 --- a/src/Bit.Build.props +++ b/src/Bit.Build.props @@ -8,7 +8,7 @@ bit platform $(MSBuildProjectName) $(MSBuildProjectName) - Copyright © bit platform 2024 + Copyright © bit platform 2025 https://github.com/bitfoundation/bitplatform @@ -27,7 +27,7 @@ https://github.com/bitfoundation/bitplatform - 9.1.2 + 9.2.0 $(ReleaseVersion) https://github.com/bitfoundation/bitplatform/releases/tag/v-$(ReleaseVersion) $([System.String]::Copy($(ReleaseVersion)).Replace('-pre-', '.')) diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitAppShell.razor b/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitAppShell.razor new file mode 100644 index 0000000000..9ddbeb6157 --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitAppShell.razor @@ -0,0 +1,23 @@ +@namespace Bit.BlazorUI +@inherits BitComponentBase + +
+
+
+
+
+ + @ChildContent + +
+
+
+
+
\ No newline at end of file diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitAppShell.razor.cs b/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitAppShell.razor.cs new file mode 100644 index 0000000000..2b65b7e6cb --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitAppShell.razor.cs @@ -0,0 +1,52 @@ +namespace Bit.BlazorUI; + +public partial class BitAppShell : BitComponentBase +{ + private ElementReference _containerRef = default!; + + + [Inject] private IJSRuntime _js { get; set; } = default!; + + + + /// + /// The cascading values to be provided for the children of the layout. + /// + [Parameter] public IEnumerable? CascadingValues { get; set; } + + /// + /// The content of the layout. + /// + [Parameter] public RenderFragment? ChildContent { get; set; } + + /// + /// Custom CSS classes for different parts of the layout. + /// + [Parameter] public BitAppShellClassStyles? Classes { get; set; } + + /// + /// Custom CSS styles for different parts of the layout. + /// + [Parameter] public BitAppShellClassStyles? Styles { get; set; } + + + + public async Task GoToTop() + { + await _js.BitExtrasGoToTop(_containerRef); + } + + + + protected override string RootElementClass => "bit-ash"; + + protected override void RegisterCssClasses() + { + ClassBuilder.Register(() => Classes?.Root); + } + + protected override void RegisterCssStyles() + { + StyleBuilder.Register(() => Styles?.Root); + } +} diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitAppShell.scss b/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitAppShell.scss new file mode 100644 index 0000000000..f9aa459c37 --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitAppShell.scss @@ -0,0 +1,54 @@ +@import '../../Styles/extra-variables.scss'; +@import '../../../Bit.BlazorUI/Styles/functions.scss'; + +.bit-ash { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + background-color: $clr-bg-pri; +} + +.bit-ash-top { + width: 100%; + z-index: 999999; + height: $bit-env-inset-top; + background-color: $clr-bg-pri; +} + +.bit-ash-bottom { + width: 100%; + z-index: 999999; + height: $bit-env-inset-bottom; + background-color: $clr-bg-pri; +} + +.bit-ash-center { + width: 100%; + display: flex; + height: calc(100% - $bit-env-inset-top - $bit-env-inset-bottom); +} + +.bit-ash-main { + height: 100%; + display: flex; + overflow: auto; + position: relative; + scroll-behavior: smooth; + overscroll-behavior: none; + width: calc(100% - $bit-env-inset-left - $bit-env-inset-right); +} + +.bit-ash-left { + height: 100%; + z-index: 999999; + width: $bit-env-inset-left; + background-color: $clr-bg-pri; +} + +.bit-ash-right { + height: 100%; + z-index: 999999; + width: $bit-env-inset-right; + background-color: $clr-bg-pri; +} diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitAppShellClassStyles.cs b/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitAppShellClassStyles.cs new file mode 100644 index 0000000000..703b86ce31 --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitAppShellClassStyles.cs @@ -0,0 +1,39 @@ +namespace Bit.BlazorUI; + +public class BitAppShellClassStyles +{ + /// + /// Custom CSS classes/styles for the root of the BitAppShell. + /// + public string? Root { get; set; } + + /// + /// Custom CSS classes/styles for the top area of the BitAppShell. + /// + public string? Top { get; set; } + + /// + /// Custom CSS classes/styles for the center area of the BitAppShell. + /// + public string? Center { get; set; } + + /// + /// Custom CSS classes/styles for the left area of the BitAppShell. + /// + public string? Left { get; set; } + + /// + /// Custom CSS classes/styles for the main area of the BitAppShell. + /// + public string? Main { get; set; } + + /// + /// Custom CSS classes/styles for the right area of the BitAppShell. + /// + public string? Right { get; set; } + + /// + /// Custom CSS classes/styles for the bottom area of the BitAppShell. + /// + public string? Bottom { get; set; } +} diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitCascadingValue.cs b/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitCascadingValue.cs new file mode 100644 index 0000000000..16f09199d0 --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitCascadingValue.cs @@ -0,0 +1,44 @@ +namespace Bit.BlazorUI; + +/// +/// The cascading value to be provided using the component. +/// +public class BitCascadingValue +{ + /// + /// The optional name of the cascading value. + /// + public string? Name { get; set; } + + /// + /// The value to be provided. + /// + public object? Value { get; set; } + + /// + /// If true, indicates that will not change. + /// + public bool IsFixed { get; set; } + + + + public BitCascadingValue() { } + public BitCascadingValue(object? value, string? name = null) : this(value, name, false) { } + public BitCascadingValue(object? value, bool isFixed) : this(value, null, isFixed) { } + public BitCascadingValue(object? value, string? name, bool isFixed) + { + Value = value; + Name = name; + IsFixed = isFixed; + } + + + + public static implicit operator BitCascadingValue(int value) => new(value); + public static implicit operator BitCascadingValue(int? value) => new(value); + public static implicit operator BitCascadingValue(bool value) => new(value); + public static implicit operator BitCascadingValue(bool? value) => new(value); + public static implicit operator BitCascadingValue(string value) => new(value); + public static implicit operator BitCascadingValue(BitDir? value) => new(value); + public static implicit operator BitCascadingValue(RouteData value) => new(value); +} diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitCascadingValueProvider.cs b/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitCascadingValueProvider.cs new file mode 100644 index 0000000000..dde4e2a9b8 --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/AppShell/BitCascadingValueProvider.cs @@ -0,0 +1,69 @@ +using System.Diagnostics.CodeAnalysis; + +namespace Bit.BlazorUI; + +/// +/// A component that provides a list of cascading values to all descendant components. +/// +public class BitCascadingValueProvider : ComponentBase +{ + /// + /// The content to which the values should be provided. + /// + [Parameter] public RenderFragment? ChildContent { get; set; } + + /// + /// The cascading values to be provided for the children. + /// + [Parameter] public IEnumerable? Values { get; set; } + + + + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] + private Type _cascadingValueType = typeof(CascadingValue<>); + + + + [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(BitCascadingValue))] + protected override void BuildRenderTree(RenderTreeBuilder builder) + { + var seq = 0; + RenderFragment? rf = ChildContent; + + foreach (var value in Values ?? []) + { + if (value.Value is null) continue; + + var r = rf; + var s = seq; + var v = value; + + rf = b => { CreateCascadingValue(b, s, v.Name, v.Value, v.IsFixed, r); }; + + seq += v.Name.HasValue() ? 5 : 4; + } + + builder.AddContent(seq, rf); + } + + + private void CreateCascadingValue(RenderTreeBuilder builder, + int seq, + string? name, + object value, + bool isFixed, + RenderFragment? childContent) + { +#pragma warning disable IL2055 // Either the type on which the MakeGenericType is called can't be statically determined, or the type parameters to be used for generic arguments can't be statically determined. + builder.OpenComponent(seq, _cascadingValueType.MakeGenericType(value.GetType())); +#pragma warning restore IL2055 // Either the type on which the MakeGenericType is called can't be statically determined, or the type parameters to be used for generic arguments can't be statically determined. + if (name.HasValue()) + { + builder.AddComponentParameter(++seq, "Name", name); + } + builder.AddComponentParameter(++seq, "Value", value); + builder.AddComponentParameter(++seq, "IsFixed", isFixed); + builder.AddComponentParameter(++seq, "ChildContent", childContent); + builder.CloseComponent(); + } +} diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/Chart/JsInterop/BitChartJavascriptHandler.cs b/src/BlazorUI/Bit.BlazorUI.Extras/Components/Chart/JsInterop/BitChartJavascriptHandler.cs index 7436279d0c..9a9dcdd886 100644 --- a/src/BlazorUI/Bit.BlazorUI.Extras/Components/Chart/JsInterop/BitChartJavascriptHandler.cs +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/Chart/JsInterop/BitChartJavascriptHandler.cs @@ -25,7 +25,7 @@ public class BitChartJavascriptHandler : IBitChartMethodHandler /// The namespace and name of a JavaScript function (see for details). public BitChartJavascriptHandler(string methodName) { - if (string.IsNullOrWhiteSpace(methodName)) + if (methodName.HasNoValue()) throw new ArgumentException("The method name cannot be null or whitespace. It has to include the namespace and name of the js-function."); if (methodName.Length < 3 || methodName.Count(c => c == '.') > 1) diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/Chart/Util/ExpandoObjectExtensions.cs b/src/BlazorUI/Bit.BlazorUI.Extras/Components/Chart/Util/ExpandoObjectExtensions.cs index 4dff5d151b..e10abf7b69 100644 --- a/src/BlazorUI/Bit.BlazorUI.Extras/Components/Chart/Util/ExpandoObjectExtensions.cs +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/Chart/Util/ExpandoObjectExtensions.cs @@ -21,7 +21,7 @@ public static ExpandoObject EnsurePathExists(this ExpandoObject value, string pa { value ??= new ExpandoObject(); - if (string.IsNullOrWhiteSpace(path)) return value; + if (path.HasNoValue()) return value; string[] segments = path.Split('.'); IDictionary source = value; @@ -80,10 +80,10 @@ public static bool PathExists(this ExpandoObject value, string path, out object[ /// public static IEnumerable EnumeratePath(this ExpandoObject value, string path) { - if (value == null) + if (value is null) throw new ArgumentNullException(nameof(value)); - if (string.IsNullOrWhiteSpace(path)) + if (path.HasNoValue()) throw new ArgumentException("The path cannot be null or whitespace."); string[] segments = path.Split('.'); @@ -131,7 +131,7 @@ public static object GetValue(this ExpandoObject value, string path) /// public static ExpandoObject SetValue(this ExpandoObject expando, string path, object value) { - if (string.IsNullOrWhiteSpace(path)) + if (path.HasNoValue()) throw new ArgumentException("The path cannot be null or whitespace."); string[] segments = path.Split('.'); diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scss b/src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scss index e3cf74ab70..e2551fddd2 100644 --- a/src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scss +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scss @@ -41,7 +41,7 @@ } .col-sort-desc .sort-indicator { - transform: scaleY(-1) translateY(2px); + transform: scaleY(-1) translateY(-2px); } /* Deep to make it easy for people adding a col-options-button element in a custom HeaderTemplate */ th .col-options-button { diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cs b/src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cs index 1a2886e7f4..3fe85ed0bc 100644 --- a/src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cs +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cs @@ -37,7 +37,7 @@ protected override void OnParametersSet() _lastAssignedProperty = Property; var compiledPropertyExpression = Property.Compile(); - if (!string.IsNullOrEmpty(Format)) + if (Format.HasValue()) { if (typeof(IFormattable).IsAssignableFrom(typeof(TProp))) { diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/NavPanel/BitNavPanel.razor b/src/BlazorUI/Bit.BlazorUI.Extras/Components/NavPanel/BitNavPanel.razor new file mode 100644 index 0000000000..7476e5a453 --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/NavPanel/BitNavPanel.razor @@ -0,0 +1,118 @@ +@namespace Bit.BlazorUI +@inherits BitComponentBase +@typeparam TItem + +@if (IsOpen) +{ +
+} + +@{ + var isToggled = (NoToggle is false) && IsToggled; +} + +
+ +
+ @if (Header is not null) + { + @Header + } + else + { +
+ @if (IconUrl.HasValue()) + { + + } + +
+ + @if (NoToggle is false) + { + + } +
+ } + + + + @if (isToggled) + { + + } + + @if (_filteredNavItems.Any() is false) + { + if (isToggled is false) + { + if (EmptyListTemplate is not null) + { + @EmptyListTemplate + } + else + { + + @(EmptyListMessage ?? "Nothing found!") + + } + } + } + else + { + + } + + + + @if (Footer is not null) + { + @Footer + } +
+ +
\ No newline at end of file diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/NavPanel/BitNavPanel.razor.cs b/src/BlazorUI/Bit.BlazorUI.Extras/Components/NavPanel/BitNavPanel.razor.cs new file mode 100644 index 0000000000..435c226fdb --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/NavPanel/BitNavPanel.razor.cs @@ -0,0 +1,255 @@ +namespace Bit.BlazorUI; + +public partial class BitNavPanel : BitComponentBase, IDisposable where TItem : class +{ + private bool _disposed; + private decimal diffXPanel; + private BitNav _bitNavRef = default!; + private IList _filteredNavItems = []; + private BitSearchBox _searchBoxRef = default!; + private IEnumerable _flatNavItemList = []; + + + [Inject] private IJSRuntime _js { get; set; } = default!; + + + + /// + /// Custom CSS classes for different parts of the nav panel. + /// + [Parameter] public BitNavPanelClassStyles? Classes { get; set; } + + /// + /// The custom template for when the search result is empty. + /// + [Parameter] public RenderFragment? EmptyListTemplate { get; set; } + + /// + /// The custom message for when the search result is empty. + /// + [Parameter] public string? EmptyListMessage { get; set; } + + /// + /// The custom template to render as the footer of the nav panel. + /// + [Parameter] public RenderFragment? Footer { get; set; } + + /// + /// The custom template to render as the header of the nav panel. + /// + [Parameter] public RenderFragment? Header { get; set; } + + /// + /// The icon url to show in the header of the nav panel. + /// + [Parameter] public string? IconUrl { get; set; } + + /// + /// Determines if the nav panel is open in small screens. + /// + [Parameter, TwoWayBound, ResetClassBuilder] + public bool IsOpen { get; set; } + + /// + /// Determines if the nav panel is in the toggled state. + /// + [Parameter, TwoWayBound] + public bool IsToggled { get; set; } + + /// + /// A collection of items to display in the nav panel. + /// + [Parameter] public IList Items { get; set; } = []; + + /// + /// Custom CSS classes for different parts of the nav component of the nav panel. + /// + [Parameter] public BitNavClassStyles? NavClasses { get; set; } + + /// + /// Custom CSS styles for different parts of the nav component of the nav panel. + /// + [Parameter] public BitNavClassStyles? NavStyles { get; set; } + + /// + /// Disables the padded mode of the nav panel. + /// + [Parameter, ResetClassBuilder] + public bool NoPad { get; set; } + + /// + /// Disables the toggle feature of the nav panel. + /// + [Parameter] public bool NoToggle { get; set; } + + /// + /// Event fired up when an item is clicked. + /// + [Parameter] public EventCallback OnItemClick { get; set; } + + /// + /// Custom CSS classes for different parts of the search box of the nav panel. + /// + [Parameter] public BitSearchBoxClassStyles? SearchBoxClasses { get; set; } + + /// + /// The placeholder of the input element of the search box of the nav panel. + /// + [Parameter] public string? SearchBoxPlaceholder { get; set; } + + /// + /// Custom CSS styles for different parts of the search box of the nav panel. + /// + [Parameter] public BitSearchBoxClassStyles? SearchBoxStyles { get; set; } + + /// + /// Custom CSS styles for different parts of the nav panel. + /// + [Parameter] public BitNavPanelClassStyles? Styles { get; set; } + + /// + /// The top CSS property value of the root element of the nav panel in px. + /// + [Parameter, ResetStyleBuilder] + public int Top { get; set; } + + + + protected override string RootElementClass => "bit-npn"; + + protected override void RegisterCssClasses() + { + ClassBuilder.Register(() => Classes?.Root); + ClassBuilder.Register(() => IsOpen ? string.Empty : "bit-npn-cls"); + ClassBuilder.Register(() => NoPad ? string.Empty : "bit-npn-pad"); + } + + protected override void RegisterCssStyles() + { + StyleBuilder.Register(() => Styles?.Root); + StyleBuilder.Register(() => Top > 0 ? $"top:{Top}px;height:calc(var(--bit-env-height-avl) - {Top}px)" : string.Empty); + } + + protected override async Task OnInitializedAsync() + { + SearchNavItems(null); + } + + private async Task HandleNavItemClick(TItem item) + { + if (_bitNavRef.GetUrl(item).HasNoValue()) return; + + await OnItemClick.InvokeAsync(item); + + await _searchBoxRef.Clear(); + + _filteredNavItems = Items; + + await ClosePanel(); + } + + private async Task ClosePanel() + { + await AssignIsOpen(false); + } + + private async Task ToggleNavPanel() + { + if (await AssignIsToggled(!IsToggled)) return; + + if (IsToggled) + { + SearchNavItems(null); + } + } + + private async Task ToggleForSearch() + { + if (await AssignIsToggled(false) is false) return; + + await Task.Delay(1); + await _searchBoxRef.FocusAsync(); + } + + private void SearchNavItems(string? searchText) + { + _filteredNavItems = Items; + if (searchText.HasNoValue()) return; + + _flatNavItemList = Items.Flatten(_bitNavRef.GetChildItems).Where(item => _bitNavRef.GetUrl(item).HasValue()); + + var mainItems = _flatNavItemList.Where(item => searchText!.Split(' ') + .Where(t => t.HasValue()) + .Any(t => $"{_bitNavRef.GetText(item)} {_bitNavRef.GetDescription(item)}" + .Contains(t, StringComparison.InvariantCultureIgnoreCase))); + + var subItems = _flatNavItemList.Where(item => searchText!.Split(' ') + .Where(t => t.HasValue()) + .Any(t => _bitNavRef.GetData(item)?.ToString()? + .Contains(t, StringComparison.InvariantCultureIgnoreCase) ?? false)); + + _filteredNavItems = [.. mainItems, .. subItems]; + } + + private decimal _oldDiffY = 0; + private void HandleOnSwipeMove(BitSwipeTrapEventArgs args) + { + if (IsOpen is false) return; + + if (Math.Abs(args.DiffX) > Math.Abs(args.DiffY)) + { + diffXPanel = args.DiffX; + StateHasChanged(); + } + else + { + var diff = args.DiffY - _oldDiffY; + _js.BitExtrasScrollBy(RootElement, 0, diff > 0 ? -10 : 10); + _oldDiffY = args.DiffY; + } + + } + private void HandleOnSwipeEnd(BitSwipeTrapEventArgs args) + { + if (IsOpen is false) return; + + diffXPanel = 0; + StateHasChanged(); + } + private async Task HandleOnSwipeTrigger(BitSwipeTrapTriggerArgs args) + { + if (IsOpen is false) return; + + if ((Dir != BitDir.Rtl && args.Direction == BitSwipeDirection.Left) || + (Dir == BitDir.Rtl && args.Direction == BitSwipeDirection.Right)) + { + diffXPanel = 0; + await ClosePanel(); + StateHasChanged(); + } + } + + private string? GetPanelStyle() + { + if (IsOpen is false) return StyleBuilder.Value; + + var translate = ((Dir != BitDir.Rtl && diffXPanel < 0) || (Dir == BitDir.Rtl && diffXPanel > 0)) + ? $"transform: translateX({diffXPanel}px)" + : string.Empty; + return $"{translate};{StyleBuilder.Value}".Trim(';'); + } + + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing is false || _disposed) return; + + _disposed = true; + } +} diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/NavPanel/BitNavPanel.scss b/src/BlazorUI/Bit.BlazorUI.Extras/Components/NavPanel/BitNavPanel.scss new file mode 100644 index 0000000000..a2842436b8 --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/NavPanel/BitNavPanel.scss @@ -0,0 +1,125 @@ +@import "../../Styles/extra-variables.scss"; +@import "../../../Bit.BlazorUI/Styles/functions.scss"; +@import "../../../Bit.BlazorUI/Styles/media-queries.scss"; + +.bit-npn { + top: 0; + position: sticky; + overflow: hidden auto; + max-width: spacing(28); + min-width: spacing(28); + background-color: $clr-bg-pri; + height: $bit-env-height-available; + + @include lt-md { + left: 0; + padding: 0; + opacity: 1; + position: fixed; + height: unset !important; + z-index: $zindex-callout; + bottom: $bit-env-inset-bottom; + top: $bit-env-inset-top !important; + transition: transform 150ms ease-out, opacity 100ms ease-in; + + &.bit-rtl { + right: 0; + left: unset; + } + + &.bit-npn-cls { + opacity: 0; + transform: translateX(-100%); + + &.bit-rtl { + transform: translateX(100%); + } + } + } + + &.bit-npn-tgl { + min-width: spacing(6); + max-width: spacing(6); + + .bit-npn-cnt { + align-items: center; + } + + &.bit-npn-pad { + min-width: spacing(12); + max-width: spacing(12); + } + } + + &.bit-npn-pad { + padding: spacing(2); + + @include lt-md { + padding: 0; + + &.bit-npn-tgl { + min-width: spacing(8); + max-width: spacing(8); + } + } + + .bit-npn-cnt { + padding: spacing(1); + background-color: $clr-bg-sec; + } + } + + &::-webkit-scrollbar { + width: 0; + } + + .bit-srb, .bit-srb-cnt { + width: 100%; + } +} + +.bit-macos .bit-npn { + height: -webkit-fill-available; + + .bit-npn-cnt { + height: -webkit-fill-available; + } +} + +.bit-npn-ovl { + inset: 0; + width: 100%; + height: 100%; + position: fixed; + min-height: 100vh; + z-index: $zindex-overlay; + background-color: $clr-bg-overlay; + + @include gt-sm { + display: none; + } +} + +.bit-npn-cnt { + width: auto; + display: flex; + gap: spacing(2); + min-height: 100%; + height: fit-content; + flex-direction: column; +} + +.bit-npn-hdr { + display: flex; + align-items: center; + justify-content: center; +} + +.bit-npn-img { + max-width: spacing(4.75); + max-height: spacing(4.75); +} + +.bit-npn-spc { + flex-grow: 1; +} diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/NavPanel/BitNavPanelClassStyles.cs b/src/BlazorUI/Bit.BlazorUI.Extras/Components/NavPanel/BitNavPanelClassStyles.cs new file mode 100644 index 0000000000..581bb5d194 --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/NavPanel/BitNavPanelClassStyles.cs @@ -0,0 +1,54 @@ +namespace Bit.BlazorUI; + +public class BitNavPanelClassStyles +{ + /// + /// Custom CSS classes/styles for the overlay of the BitNavPanel. + /// + public string? Overlay { get; set; } + + /// + /// Custom CSS classes/styles for the root element of the BitNavPanel. + /// + public string? Root { get; set; } + + /// + /// Custom CSS classes/styles for the container of the BitNavPanel. + /// + public string? Container { get; set; } + + /// + /// Custom CSS classes/styles for the header container of the BitNavPanel. + /// + public string? Header { get; set; } + + /// + /// Custom CSS classes/styles for the header icon of the BitNavPanel. + /// + public string? HeaderIcon { get; set; } + + /// + /// Custom CSS classes/styles for the toggle button of the BitNavPanel. + /// + public string? ToggleButton { get; set; } + + /// + /// Custom CSS classes/styles for the search box of the BitNavPanel. + /// + public string? SearchBox { get; set; } + + /// + /// Custom CSS classes/styles for the toggle search button of the BitNavPanel. + /// + public string? ToggleSearchButton { get; set; } + + /// + /// Custom CSS classes/styles for the text element of the empty list message of the BitNavPanel. + /// + public string? EmptyListMessage { get; set; } + + /// + /// Custom CSS classes/styles for the nav component of the BitNavPanel. + /// + public string? Nav { get; set; } +} diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/IServiceCollectionExtensions.cs b/src/BlazorUI/Bit.BlazorUI.Extras/Extensions/IServiceCollectionExtensions.cs similarity index 94% rename from src/BlazorUI/Bit.BlazorUI.Extras/IServiceCollectionExtensions.cs rename to src/BlazorUI/Bit.BlazorUI.Extras/Extensions/IServiceCollectionExtensions.cs index 0ae549d8eb..a6bc011de1 100644 --- a/src/BlazorUI/Bit.BlazorUI.Extras/IServiceCollectionExtensions.cs +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Extensions/IServiceCollectionExtensions.cs @@ -22,6 +22,8 @@ public static IServiceCollection AddBitBlazorUIExtrasServices(this IServiceColle services.TryAddScoped(); } + services.TryAddScoped(); + return services; } } diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Extensions/JsInterop/BitExtrasJsRuntimeExtensions.cs b/src/BlazorUI/Bit.BlazorUI.Extras/Extensions/JsInterop/BitExtrasJsRuntimeExtensions.cs new file mode 100644 index 0000000000..7a55e2fc1a --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Extensions/JsInterop/BitExtrasJsRuntimeExtensions.cs @@ -0,0 +1,19 @@ +namespace Bit.BlazorUI; + +internal static class BitExtrasJsRuntimeExtensions +{ + internal static ValueTask BitExtrasApplyRootClasses(this IJSRuntime jsRuntime, List cssClasses, Dictionary cssVariables) + { + return jsRuntime.InvokeVoid("BitBlazorUI.BitExtras.applyRootClasses", cssClasses, cssVariables); + } + + internal static ValueTask BitExtrasGoToTop(this IJSRuntime jsRuntime, ElementReference element) + { + return jsRuntime.InvokeVoid("BitBlazorUI.BitExtras.goToTop", element); + } + + internal static ValueTask BitExtrasScrollBy(this IJSRuntime jsRuntime, ElementReference element, decimal x, decimal y) + { + return jsRuntime.InvokeVoid("BitBlazorUI.BitExtras.scrollBy", element, x, y); + } +} diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Extensions/LinqExtensions.cs b/src/BlazorUI/Bit.BlazorUI.Extras/Extensions/LinqExtensions.cs new file mode 100644 index 0000000000..4c953a5a96 --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Extensions/LinqExtensions.cs @@ -0,0 +1,49 @@ +namespace Bit.BlazorUI; + +/// +/// https://www.codeproject.com/tips/375967/flatten-a-hierarchical-collection-of-objects-with +/// +public static class LinqExtensions +{ + /// + /// This method extends the LINQ methods to flatten a collection of + /// items that have a property of children of the same type. + /// + /// Item type. + /// Source collection. + /// + /// Child property selector delegate of each item. + /// IEnumerable'T' childPropertySelector(T itemBeingFlattened) + /// + /// Returns a one level list of elements of type T. + public static IEnumerable Flatten(this IEnumerable source, + Func> childPropertySelector) + { + return source + .Flatten((itemBeingFlattened, objectsBeingFlattened) => + childPropertySelector(itemBeingFlattened)); + } + + /// + /// This method extends the LINQ methods to flatten a collection of + /// items that have a property of children of the same type. + /// + /// Item type. + /// Source collection. + /// + /// Child property selector delegate of each item. + /// IEnumerable'T' childPropertySelector + /// (T itemBeingFlattened, IEnumerable'T' objectsBeingFlattened) + /// + /// Returns a one level list of elements of type T. + public static IEnumerable Flatten(this IEnumerable source, + Func, IEnumerable> childPropertySelector) + { + return source + .Concat(source + .Where(item => childPropertySelector(item, source) != null) + .SelectMany(itemBeingFlattened => + childPropertySelector(itemBeingFlattened, source) + .Flatten(childPropertySelector))); + } +} diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Scripts/BitExtras.ts b/src/BlazorUI/Bit.BlazorUI.Extras/Scripts/BitExtras.ts new file mode 100644 index 0000000000..b2463e681f --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Scripts/BitExtras.ts @@ -0,0 +1,20 @@ +namespace BitBlazorUI { + export class BitExtras { + public static applyRootClasses(cssClasses: string[], cssVariables: any) { + cssClasses?.forEach(c => document.documentElement.classList.add(c)); + Object.keys(cssVariables).forEach(key => document.documentElement.style.setProperty(key, cssVariables[key])); + } + + public static goToTop(element: HTMLElement) { + if (!element) return; + + element.scrollTo({ top: 0 }); + } + + public static scrollBy(element: HTMLElement, x: number, y: number) { + if (!element) return; + + element.scrollBy(x, y); + } + } +} \ No newline at end of file diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Scripts/general.ts b/src/BlazorUI/Bit.BlazorUI.Extras/Scripts/general.ts new file mode 100644 index 0000000000..d19e62953b --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Scripts/general.ts @@ -0,0 +1,4 @@ +window.addEventListener('load', () => { + document.documentElement.style.setProperty('--bit-env-win-width', `${window.innerWidth}px`); + document.documentElement.style.setProperty('--bit-env-win-height', `${window.innerHeight}px`); +}); \ No newline at end of file diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Services/BitExtraServices.cs b/src/BlazorUI/Bit.BlazorUI.Extras/Services/BitExtraServices.cs new file mode 100644 index 0000000000..e0faef2997 --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Services/BitExtraServices.cs @@ -0,0 +1,34 @@ +namespace Bit.BlazorUI; + +public class BitExtraServices(IJSRuntime js) +{ + public async Task AddRootCssClasses() + { + var cssClasses = new List(); + + if (OperatingSystem.IsBrowser()) + { + cssClasses.Add("bit-browser"); + } + else if (OperatingSystem.IsWindows()) + { + cssClasses.Add("bit-windows"); + } + else if (OperatingSystem.IsMacOS() || OperatingSystem.IsMacCatalyst()) + { + cssClasses.Add("bit-macos"); + } + else if (OperatingSystem.IsIOS() && OperatingSystem.IsMacCatalyst() is false) + { + cssClasses.Add("bit-ios"); + } + else if (OperatingSystem.IsAndroid()) + { + cssClasses.Add("bit-android"); + } + + var cssVariables = new Dictionary(); + + await js.BitExtrasApplyRootClasses(cssClasses, cssVariables); + } +} diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Styles/bit.blazorui.extras.scss b/src/BlazorUI/Bit.BlazorUI.Extras/Styles/bit.blazorui.extras.scss index 4d58f1782c..eb02b8b603 100644 --- a/src/BlazorUI/Bit.BlazorUI.Extras/Styles/bit.blazorui.extras.scss +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Styles/bit.blazorui.extras.scss @@ -1,2 +1,3 @@ -@import "components.scss"; +@import "general.scss"; +@import "components.scss"; @import "fabric.mdl2.bit.blazoui.extras.scss"; diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Styles/components.scss b/src/BlazorUI/Bit.BlazorUI.Extras/Styles/components.scss index ca46bd9aef..026cf642cb 100644 --- a/src/BlazorUI/Bit.BlazorUI.Extras/Styles/components.scss +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Styles/components.scss @@ -1,4 +1,6 @@ -@import "../Components/DataGrid/BitDataGrid.scss"; +@import "../Components/AppShell/BitAppShell.scss"; +@import "../Components/DataGrid/BitDataGrid.scss"; @import "../Components/DataGrid/Pagination/BitDataGridPaginator.scss"; +@import "../Components/NavPanel/BitNavPanel.scss"; @import "../Components/PdfReader/BitPdfReader.scss"; @import "../Components/ProPanel/BitProPanel.scss"; diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-variables.scss b/src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-variables.scss new file mode 100644 index 0000000000..8f09e8a4e9 --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-variables.scss @@ -0,0 +1,17 @@ +$bit-env-inset-top: var(--bit-env-inset-top); +$bit-env-inset-left: var(--bit-env-inset-left); +$bit-env-inset-right: var(--bit-env-inset-right); +$bit-env-inset-bottom: var(--bit-env-inset-bottom); +//-- +$bit-env-width-vw: var(--bit-env-width-vw); +$bit-env-height-vh: var(--bit-env-height-vh); +$bit-env-width-percent: var(--bit-env-width-per); +$bit-env-height-percent: var(--bit-env-height-per); +$bit-env-width-available: var(--bit-env-width-avl); +$bit-env-height-available: var(--bit-env-height-avl); +//-- +$bit-env-inset-inline-start: var(--bit-env-inset-inline-start); +$bit-env-inset-inline-end: var(--bit-env-inset-inline-end); +//-- +$bit-env-window-width: var(--bit-env-win-width); +$bit-env-window-height: var(--bit-env-win-height); diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Styles/fabric.mdl2.bit.blazoui.extras.scss b/src/BlazorUI/Bit.BlazorUI.Extras/Styles/fabric.mdl2.bit.blazoui.extras.scss index e372997a9a..736da0b952 100644 --- a/src/BlazorUI/Bit.BlazorUI.Extras/Styles/fabric.mdl2.bit.blazoui.extras.scss +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Styles/fabric.mdl2.bit.blazoui.extras.scss @@ -5,3 +5,15 @@ font-family: 'Fabric MDL2 bit BlazorUI Extras'; src: url('../fonts/FabMDL2.4.66.bit.BlazorUI.Extras.woff2') format("woff2"); } + +.bit-icon-ex { + font-style: normal; + font-weight: normal; + display: inline-block; + font-family: 'Fabric MDL2 bit BlazorUI Extras' !important; +} + +.bit-icon-ex--ChevronLeftEnd6:before { content: "\F371"; } +.bit-icon-ex--ChevronLeftSmall:before { content: "\E96F"; } +.bit-icon-ex--More:before { content: "\E712"; } +.bit-icon-ex--ColumnRightTwoThirds:before { content: "\F1D7"; } \ No newline at end of file diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Styles/general.scss b/src/BlazorUI/Bit.BlazorUI.Extras/Styles/general.scss new file mode 100644 index 0000000000..d77e2b499d --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Styles/general.scss @@ -0,0 +1,21 @@ +:root { + --bit-env-inset-top: env(safe-area-inset-top, 0px); + --bit-env-inset-left: env(safe-area-inset-left, 0px); + --bit-env-inset-right: env(safe-area-inset-right, 0px); + --bit-env-inset-bottom: env(safe-area-inset-bottom, 0px); + //-- + --bit-env-width-vw: calc(100vw - var(--bit-env-inset-left) - var(--bit-env-inset-right)); + --bit-env-height-vh: calc(100vh - var(--bit-env-inset-top) - var(--bit-env-inset-bottom)); + --bit-env-width-per: calc(100% - var(--bit-env-inset-left) - var(--bit-env-inset-right)); + --bit-env-height-per: calc(100% - var(--bit-env-inset-top) - var(--bit-env-inset-bottom)); + --bit-env-width-avl: calc(var(--bit-env-win-width) - var(--bit-env-inset-left) - var(--bit-env-inset-right)); + --bit-env-height-avl: calc(var(--bit-env-win-height) - var(--bit-env-inset-top) - var(--bit-env-inset-bottom)); + //-- + --bit-env-inset-inline-start: var(--bit-env-inset-left); + --bit-env-inset-inline-end: var(--bit-env-inset-right); + + [dir="rtl"] { + --bit-env-inset-inline-start: var(--bit-env-inset-right); + --bit-env-inset-inline-end: var(--bit-env-inset-left); + } +} diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/fonts/FabMDL2.4.66.bit.BlazorUI.Extras.woff2 b/src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/fonts/FabMDL2.4.66.bit.BlazorUI.Extras.woff2 index ff70846337..d8cd1d72af 100644 Binary files a/src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/fonts/FabMDL2.4.66.bit.BlazorUI.Extras.woff2 and b/src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/fonts/FabMDL2.4.66.bit.BlazorUI.Extras.woff2 differ diff --git a/src/BlazorUI/Bit.BlazorUI.Tests/Bit.BlazorUI.Tests.csproj b/src/BlazorUI/Bit.BlazorUI.Tests/Bit.BlazorUI.Tests.csproj index cb16dd5cbb..120da4bfd8 100644 --- a/src/BlazorUI/Bit.BlazorUI.Tests/Bit.BlazorUI.Tests.csproj +++ b/src/BlazorUI/Bit.BlazorUI.Tests/Bit.BlazorUI.Tests.csproj @@ -15,9 +15,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitButtonGroup/BitButtonGroup.razor b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitButtonGroup/BitButtonGroup.razor index 34a0df0ad6..790fc14f3f 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitButtonGroup/BitButtonGroup.razor +++ b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitButtonGroup/BitButtonGroup.razor @@ -22,7 +22,7 @@ disabled="@(isEnabled is false)" aria-disabled="@(isEnabled is false)" title="@GetItemTitle(item)" - style="@GetStyle(item)" + style="@GetItemStyle(item)" class="@GetItemClass(item)"> @if (template is not null) { @@ -37,13 +37,13 @@ var iconName = GetItemIconName(item); @if (iconName.HasValue()) { - + } var text = GetItemText(item); if (text.HasValue()) { - @text + @text } } diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitButtonGroup/BitButtonGroup.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitButtonGroup/BitButtonGroup.razor.cs index 73b9ff5894..ad846198c6 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitButtonGroup/BitButtonGroup.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitButtonGroup/BitButtonGroup.razor.cs @@ -21,12 +21,23 @@ public partial class BitButtonGroup : BitComponentBase where TItem : clas /// [Parameter] public RenderFragment? ChildContent { get; set; } + /// + /// Custom CSS classes for different parts of the ButtonGroup. + /// + [Parameter] public BitButtonGroupClassStyles? Classes { get; set; } + /// /// Defines the general colors available in the bit BlazorUI. /// [Parameter, ResetClassBuilder] public BitColor? Color { get; set; } + /// + /// Expand the ButtonGroup width to 100% of the available width. + /// + [Parameter, ResetClassBuilder] + public bool FullWidth { get; set; } + /// /// Determines that only the icon should be rendered. /// @@ -63,10 +74,15 @@ public partial class BitButtonGroup : BitComponentBase where TItem : clas [Parameter, ResetClassBuilder] public BitSize? Size { get; set; } + /// + /// Custom CSS styles for different parts of the ButtonGroup. + /// + [Parameter] public BitButtonGroupClassStyles? Styles { get; set; } + /// /// Display ButtonGroup with toggle mode enabled for each button. /// - [Parameter] public bool Toggled { get; set; } + [Parameter] public bool Toggle { get; set; } /// /// The visual variant of the button group. @@ -103,6 +119,8 @@ internal void UnregisterOption(BitButtonGroupOption option) protected override void RegisterCssClasses() { + ClassBuilder.Register(() => Classes?.Root); + ClassBuilder.Register(() => Variant switch { BitVariant.Fill => "bit-btg-fil", @@ -142,6 +160,13 @@ protected override void RegisterCssClasses() }); ClassBuilder.Register(() => Vertical ? "bit-btg-vrt" : string.Empty); + + ClassBuilder.Register(() => FullWidth ? "bit-btg-flw" : string.Empty); + } + + protected override void RegisterCssStyles() + { + StyleBuilder.Register(() => Styles?.Root); } protected override void OnParametersSet() @@ -186,7 +211,7 @@ private async Task HandleOnItemClick(TItem item) } } - if (Toggled) + if (Toggle) { if (_toggleItem == item) { @@ -211,6 +236,11 @@ private async Task HandleOnItemClick(TItem item) if (_toggleItem == item) { classes.Add("bit-btg-chk"); + + if (Classes?.ToggledButton.HasValue() ?? false) + { + classes.Add(Classes.ToggledButton!); + } } var classItem = GetClass(item); @@ -219,14 +249,42 @@ private async Task HandleOnItemClick(TItem item) classes.Add(classItem!); } + if (Classes?.Button.HasValue() ?? false) + { + classes.Add(Classes.Button!); + } + return string.Join(' ', classes); } + private string? GetItemStyle(TItem? item) + { + List styles = new(); + + var style = GetStyle(item); + if (style.HasValue()) + { + styles.Add(style!.Trim(';')); + } + + if (Styles?.Button.HasValue() ?? false) + { + styles.Add(Styles.Button!.Trim(';')); + } + + if (_toggleItem == item && (Styles?.ToggledButton.HasValue() ?? false)) + { + styles.Add(Styles.ToggledButton!); + } + + return string.Join(';', styles); + } + private string? GetItemText(TItem? item) { if (IconOnly) return null; - if (Toggled) + if (Toggle) { if (_toggleItem == item) { @@ -251,7 +309,7 @@ private async Task HandleOnItemClick(TItem item) private string? GetItemTitle(TItem? item) { - if (Toggled) + if (Toggle) { if (_toggleItem == item) { @@ -276,7 +334,7 @@ private async Task HandleOnItemClick(TItem item) private string? GetItemIconName(TItem? item) { - if (Toggled) + if (Toggle) { if (_toggleItem == item) { diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitButtonGroup/BitButtonGroup.scss b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitButtonGroup/BitButtonGroup.scss index 9a55b86981..3e6fb265db 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitButtonGroup/BitButtonGroup.scss +++ b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitButtonGroup/BitButtonGroup.scss @@ -2,9 +2,9 @@ .bit-btg { overflow: hidden; + width: fit-content; flex-direction: row; display: inline-flex; - max-width: fit-content; border-width: $shp-border-width; border-style: $shp-border-style; border-radius: $shp-border-radius; @@ -24,7 +24,12 @@ } } +.bit-btg-flw { + width: 100%; +} + .bit-btg-itm { + flex-grow: 1; display: flex; gap: spacing(1); cursor: pointer; diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitButtonGroup/BitButtonGroupClassStyles.cs b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitButtonGroup/BitButtonGroupClassStyles.cs new file mode 100644 index 0000000000..66dc6fb58e --- /dev/null +++ b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitButtonGroup/BitButtonGroupClassStyles.cs @@ -0,0 +1,29 @@ +namespace Bit.BlazorUI; + +public class BitButtonGroupClassStyles +{ + /// + /// Custom CSS classes/styles for the root element of the BitButtonGroup. + /// + public string? Root { get; set; } + + /// + /// Custom CSS classes/styles for the internal button of the BitButtonGroup. + /// + public string? Button { get; set; } + + /// + /// Custom CSS classes/styles for the icon of the BitButtonGroup. + /// + public string? Icon { get; set; } + + /// + /// Custom CSS classes/styles for the text of the BitButtonGroup. + /// + public string? Text { get; set; } + + /// + /// Custom CSS classes/styles for the button when in toggle mode of the BitButtonGroup. + /// + public string? ToggledButton { get; set; } +} diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitMenuButton/BitMenuButton.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitMenuButton/BitMenuButton.razor.cs index cc40b5d490..fafd8262f2 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitMenuButton/BitMenuButton.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/BitMenuButton/BitMenuButton.razor.cs @@ -568,7 +568,7 @@ private async Task ToggleCallout() { if (IsEnabled is false) return; - await _js.ToggleCallout(_dotnetObj, + await _js.BitCalloutToggleCallout(_dotnetObj, _Id, null, _calloutId, @@ -607,7 +607,7 @@ protected virtual async ValueTask DisposeAsync(bool disposing) try { - await _js.ClearCallout(_calloutId); + await _js.BitCalloutClearCallout(_calloutId); } catch (JSDisconnectedException) { } // we can ignore this exception here } diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.razor.cs index 651bbad092..5246874192 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.razor.cs @@ -944,14 +944,14 @@ private async Task HandleOnTimeHourFocus() { if (IsEnabled is false || ShowTimePicker is false) return; - await _js.SelectText(_inputTimeHourRef); + await _js.BitUtilsSelectText(_inputTimeHourRef); } private async Task HandleOnTimeMinuteFocus() { if (IsEnabled is false || ShowTimePicker is false) return; - await _js.SelectText(_inputTimeMinuteRef); + await _js.BitUtilsSelectText(_inputTimeMinuteRef); } private void ToggleAmPmTime() diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.razor.cs index ffd4a57f37..e9e5e00612 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.razor.cs @@ -170,7 +170,7 @@ protected override void Dispose(bool disposing) private async Task SetIndeterminate() { - await _js.SetProperty(InputElement, "indeterminate", Indeterminate); + await _js.BitUtilsSetProperty(InputElement, "indeterminate", Indeterminate); } private async Task HandleOnCheckboxClick(MouseEventArgs args) @@ -199,6 +199,6 @@ private async Task SetIndeterminate(bool value) { if (await AssignIndeterminate(value) is false) return; - await _js.SetProperty(InputElement, "indeterminate", value); + await _js.BitUtilsSetProperty(InputElement, "indeterminate", value); } } diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.razor.cs index f44e53b922..44691b0e09 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.razor.cs @@ -215,7 +215,7 @@ private string GetItemContainerCssStyles(TItem item) { StringBuilder cssStyle = new(); - if (string.IsNullOrEmpty(GetStyle(item)) is false) + if (GetStyle(item).HasValue()) { cssStyle.Append(GetStyle(item)); } @@ -237,7 +237,7 @@ private string GetItemContainerCssClasses(TItem item) { StringBuilder cssClass = new("bit-chg-icn"); - if (string.IsNullOrEmpty(GetClass(item)) is false) + if (GetClass(item).HasValue()) { cssClass.Append(' ').Append(GetClass(item)); } diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.razor.cs index addc3d92be..e18a8ad2b3 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.razor.cs @@ -852,7 +852,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) if (firstRender is false) return; if (Responsive is false) return; - await _js.SwipesSetup(_calloutId, 0.25m, BitPanelPosition.End, Dir is BitDir.Rtl, _dotnetObj); + await _js.BitSwipesSetup(_calloutId, 0.25m, BitPanelPosition.End, Dir is BitDir.Rtl, _dotnetObj); } protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(false)] out TValue result, [NotNullWhen(false)] out string? parsingErrorMessage) @@ -1162,7 +1162,7 @@ private async Task ToggleCallout() { if (IsEnabled is false) return; - _isResponsiveMode = await _js.ToggleCallout(_dotnetObj, + _isResponsiveMode = await _js.BitCalloutToggleCallout(_dotnetObj, _dropdownId, null, _calloutId, @@ -1252,7 +1252,7 @@ private async Task HandleOnKeyDown(KeyboardEventArgs eventArgs) } else if (eventArgs.Key == "Enter") { - _searchText = await _js.GetProperty(_isResponsiveMode ? _comboBoxInputResponsiveRef : _comboBoxInputRef, "value"); + _searchText = await _js.BitUtilsGetProperty(_isResponsiveMode ? _comboBoxInputResponsiveRef : _comboBoxInputRef, "value"); await AddDynamicItem(); @@ -1473,8 +1473,8 @@ protected virtual async ValueTask DisposeAsync(bool disposing) try { - await _js.ClearCallout(_calloutId); - await _js.SwipesDispose(_calloutId); + await _js.BitCalloutClearCallout(_calloutId); + await _js.BitSwipesDispose(_calloutId); } catch (JSDisconnectedException) { } // we can ignore this exception here diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.razor.cs index f5c0574521..7eaaa3ed12 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.razor.cs @@ -353,7 +353,7 @@ private async Task HandleOnFocusIn(FocusEventArgs e) _hasFocus = true; ClassBuilder.Reset(); StyleBuilder.Reset(); - await _js.SelectText(InputElement); + await _js.BitUtilsSelectText(InputElement); await OnFocusIn.InvokeAsync(e); } @@ -374,7 +374,7 @@ private async Task HandleOnFocus(FocusEventArgs e) _hasFocus = true; ClassBuilder.Reset(); StyleBuilder.Reset(); - await _js.SelectText(InputElement); + await _js.BitUtilsSelectText(InputElement); await OnFocus.InvokeAsync(e); } diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.razor.cs index 0e4079ff72..55adccf395 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.razor.cs @@ -141,8 +141,19 @@ public partial class BitSearchBox : BitTextInputBase, IAsyncDisposable + /// + /// Clears the input element. + /// + public async Task Clear() + { + await SetCurrentValueAsync(null); + await _js.BitUtilsSetProperty(InputElement, "value", null); + } + + + [JSInvokable("CloseCallout")] - public void CloseCalloutBeforeAnotherCalloutIsOpened() + public void _CloseCalloutBeforeAnotherCalloutIsOpened() { if (IsEnabled is false) return; @@ -264,7 +275,7 @@ private async Task HandleOnKeyDown(KeyboardEventArgs eventArgs) } else if (eventArgs.Key == "Enter") { - CurrentValue = await _js.GetProperty(InputElement, "value"); + CurrentValue = await _js.BitUtilsGetProperty(InputElement, "value"); await CloseCallout(); await OnSearch.InvokeAsync(CurrentValue); } @@ -282,7 +293,7 @@ private async Task ToggleCallout() { if (IsEnabled is false) return; - await _js.ToggleCallout(_dotnetObj, + await _js.BitCalloutToggleCallout(_dotnetObj, _Id, null, _calloutId, @@ -435,7 +446,7 @@ protected virtual async ValueTask DisposeAsync(bool disposing) try { - await _js.ClearCallout(_calloutId); + await _js.BitCalloutClearCallout(_calloutId); } catch (JSDisconnectedException) { } // we can ignore this exception here } diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.razor.cs index 5a82e5b15e..05e80f4ff0 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.razor.cs @@ -343,7 +343,7 @@ private void OnSetValues() private async ValueTask GetClientHeight(ElementReference element) { - var height = await _js.GetProperty(element, "clientHeight"); + var height = await _js.BitUtilsGetProperty(element, "clientHeight"); return height.HasNoValue() ? 0 : int.Parse(height); diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/SpinButton/BitSpinButton.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/SpinButton/BitSpinButton.razor.cs index 3835a3b806..8483f7a7b0 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/SpinButton/BitSpinButton.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/SpinButton/BitSpinButton.razor.cs @@ -440,7 +440,7 @@ private async Task HandleOnFocus(FocusEventArgs e) await OnFocus.InvokeAsync(e); - await _js.SelectText(InputElement); + await _js.BitUtilsSelectText(InputElement); } private void SetValue(double value) diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/CircularTimePicker/BitCircularTimePicker.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/CircularTimePicker/BitCircularTimePicker.razor.cs index 31936c2e66..dbe2bb9769 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/CircularTimePicker/BitCircularTimePicker.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/CircularTimePicker/BitCircularTimePicker.razor.cs @@ -307,7 +307,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) if (firstRender is false) return; - await _js.SwipesSetup(_calloutId, 0.25m, BitPanelPosition.Top, Dir is BitDir.Rtl, _dotnetObj); + await _js.BitSwipesSetup(_calloutId, 0.25m, BitPanelPosition.Top, Dir is BitDir.Rtl, _dotnetObj); _pointerUpAbortControllerId = await _js.BitCircularTimePickerRegisterPointerUp(_dotnetObj, nameof(_HandlePointerUp)); _pointerMoveAbortControllerId = await _js.BitCircularTimePickerRegisterPointerMove(_dotnetObj, nameof(_HandlePointerMove)); } @@ -523,7 +523,7 @@ private async Task ToggleCallout() if (Standalone) return; if (IsEnabled is false) return; - await _js.ToggleCallout(_dotnetObj, + await _js.BitCalloutToggleCallout(_dotnetObj, _circularTimePickerId, null, _calloutId, @@ -543,7 +543,7 @@ private async Task UpdateTime(MouseEventArgs e) { if (IsEnabled is false || InvalidValueBinding()) return; - var rect = await _js.GetBoundingClientRect(_clockRef); + var rect = await _js.BitUtilsGetBoundingClientRect(_clockRef); var radius = rect.Width / 2; var centerX = radius; var centerY = radius; @@ -707,8 +707,8 @@ protected virtual async ValueTask DisposeAsync(bool disposing) try { - await _js.ClearCallout(_calloutId); - await _js.SwipesDispose(_calloutId); + await _js.BitCalloutClearCallout(_calloutId); + await _js.BitSwipesDispose(_calloutId); await _js.BitCircularTimePickerAbort(_pointerUpAbortControllerId); await _js.BitCircularTimePickerAbort(_pointerMoveAbortControllerId); } diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/ColorPicker/BitColorPicker.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/ColorPicker/BitColorPicker.razor.cs index 593b27ce34..5ff76edc51 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/ColorPicker/BitColorPicker.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/ColorPicker/BitColorPicker.razor.cs @@ -132,7 +132,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) private async Task SetSaturationPickerThumbPositionAsync() { var (_, saturation, value) = _color.Hsv; - var saturationPickerRect = await _js.GetBoundingClientRect(_saturationPickerRef); + var saturationPickerRect = await _js.BitUtilsGetBoundingClientRect(_saturationPickerRef); var width = saturationPickerRect?.Width ?? 0; var height = saturationPickerRect?.Height ?? 0; @@ -152,7 +152,7 @@ private async Task UpdateColor(MouseEventArgs e) { if (ColorHasBeenSet && ColorChanged.HasDelegate is false) return; - var pickerRect = await _js.GetBoundingClientRect(_saturationPickerRef); + var pickerRect = await _js.BitUtilsGetBoundingClientRect(_saturationPickerRef); var left = e.ClientX < pickerRect.Left ? 0 : e.ClientX > pickerRect.Left + pickerRect.Width ? pickerRect.Width diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/DatePicker/BitDatePicker.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/DatePicker/BitDatePicker.razor.cs index 35b8b01462..1a1fc3bb62 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/DatePicker/BitDatePicker.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/DatePicker/BitDatePicker.razor.cs @@ -530,7 +530,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) if (firstRender is false) return; if (Responsive is false) return; - await _js.SwipesSetup(_calloutId, 0.25m, BitPanelPosition.Top, Dir is BitDir.Rtl, _dotnetObj); + await _js.BitSwipesSetup(_calloutId, 0.25m, BitPanelPosition.Top, Dir is BitDir.Rtl, _dotnetObj); } protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(false)] out DateTimeOffset? result, [NotNullWhen(false)] out string? validationErrorMessage) @@ -572,7 +572,7 @@ private async Task HandleOnClick() ResetPickersState(); - var bodyWidth = await _js.GetBodyWidth(); + var bodyWidth = await _js.BitUtilsGetBodyWidth(); var notEnoughWidthAvailable = bodyWidth < MAX_WIDTH; if (_showMonthPickerAsOverlayInternal is false) @@ -1279,14 +1279,14 @@ private async Task HandleOnTimeHourFocus() { if (IsEnabled is false || ShowTimePicker is false) return; - await _js.SelectText(_inputTimeHourRef); + await _js.BitUtilsSelectText(_inputTimeHourRef); } private async Task HandleOnTimeMinuteFocus() { if (IsEnabled is false || ShowTimePicker is false) return; - await _js.SelectText(_inputTimeMinuteRef); + await _js.BitUtilsSelectText(_inputTimeMinuteRef); } private void ToggleAmPmTime() @@ -1483,7 +1483,7 @@ private async Task ToggleCallout() if (Standalone) return false; if (IsEnabled is false) return false; - return await _js.ToggleCallout(_dotnetObj, + return await _js.BitCalloutToggleCallout(_dotnetObj, _datePickerId, null, _calloutId, @@ -1534,8 +1534,8 @@ protected virtual async ValueTask DisposeAsync(bool disposing) try { - await _js.ClearCallout(_calloutId); - await _js.SwipesDispose(_calloutId); + await _js.BitCalloutClearCallout(_calloutId); + await _js.BitSwipesDispose(_calloutId); } catch (JSDisconnectedException) { } // we can ignore this exception here diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/DateRangePicker/BitDateRangePicker.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/DateRangePicker/BitDateRangePicker.razor.cs index a64044a39c..09b6d848bc 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/DateRangePicker/BitDateRangePicker.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/DateRangePicker/BitDateRangePicker.razor.cs @@ -593,7 +593,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) if (firstRender is false) return; if (Responsive is false) return; - await _js.SwipesSetup(_calloutId, 0.25m, BitPanelPosition.Top, Dir is BitDir.Rtl, _dotnetObj); + await _js.BitSwipesSetup(_calloutId, 0.25m, BitPanelPosition.Top, Dir is BitDir.Rtl, _dotnetObj); } protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(false)] out BitDateRangePickerValue? result, [NotNullWhen(false)] out string? validationErrorMessage) @@ -642,7 +642,7 @@ private async Task HandleOnClick() ResetPickersState(); - var bodyWidth = await _js.GetBodyWidth(); + var bodyWidth = await _js.BitUtilsGetBodyWidth(); var notEnoughWidthAvailable = bodyWidth < MAX_WIDTH; if (_showMonthPickerAsOverlayInternal is false) @@ -1629,14 +1629,14 @@ private async Task HandleOnHourInputFocus(bool isStartTime) { if (IsEnabled is false || ShowTimePicker is false) return; - await _js.SelectText(isStartTime ? _startTimeHourInputRef : _endTimeHourInputRef); + await _js.BitUtilsSelectText(isStartTime ? _startTimeHourInputRef : _endTimeHourInputRef); } private async Task HandleOnMinuteInputFocus(bool isStartTime) { if (IsEnabled is false || ShowTimePicker is false) return; - await _js.SelectText(isStartTime ? _startTimeMinuteInputRef : _endTimeMinuteInputRef); + await _js.BitUtilsSelectText(isStartTime ? _startTimeMinuteInputRef : _endTimeMinuteInputRef); } private void HandleOnAmClick(bool isStartTime) @@ -2025,7 +2025,7 @@ private async Task ToggleCallout() if (Standalone) return false; if (IsEnabled is false) return false; - return await _js.ToggleCallout(_dotnetObj, + return await _js.BitCalloutToggleCallout(_dotnetObj, _dateRangePickerId, null, _calloutId, @@ -2076,8 +2076,8 @@ protected virtual async ValueTask DisposeAsync(bool disposing) try { - await _js.ClearCallout(_calloutId); - await _js.SwipesDispose(_calloutId); + await _js.BitCalloutClearCallout(_calloutId); + await _js.BitSwipesDispose(_calloutId); } catch (JSDisconnectedException) { } // we can ignore this exception here diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/TimePicker/BitTimePicker.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/TimePicker/BitTimePicker.razor.cs index d554b0d9ee..bea8abb564 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/TimePicker/BitTimePicker.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/_Pickers/TimePicker/BitTimePicker.razor.cs @@ -345,7 +345,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) if (firstRender is false) return; if (Responsive is false) return; - await _js.SwipesSetup(_calloutId, 0.25m, BitPanelPosition.Top, Dir is BitDir.Rtl, _dotnetObj); + await _js.BitSwipesSetup(_calloutId, 0.25m, BitPanelPosition.Top, Dir is BitDir.Rtl, _dotnetObj); } protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(false)] out TimeSpan? result, [NotNullWhen(false)] out string? validationErrorMessage) @@ -425,7 +425,7 @@ private async Task ToggleCallout() if (Standalone) return; if (IsEnabled is false) return; - await _js.ToggleCallout(_dotnetObj, + await _js.BitCalloutToggleCallout(_dotnetObj, _timePickerId, null, _calloutId, @@ -512,14 +512,14 @@ private async Task HandleOnHourFocus() { if (IsEnabled is false) return; - await _js.SelectText(_inputHourRef); + await _js.BitUtilsSelectText(_inputHourRef); } private async Task HandleOnMinuteFocus() { if (IsEnabled is false) return; - await _js.SelectText(_inputMinuteRef); + await _js.BitUtilsSelectText(_inputMinuteRef); } private async Task ChangeHour(bool isNext) @@ -673,8 +673,8 @@ protected virtual async ValueTask DisposeAsync(bool disposing) try { - await _js.ClearCallout(_calloutId); - await _js.SwipesDispose(_calloutId); + await _js.BitCalloutClearCallout(_calloutId); + await _js.BitSwipesDispose(_calloutId); } catch (JSDisconnectedException) { } // we can ignore this exception here diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayout.razor b/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayout.razor index 508c8bccab..de2e15056e 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayout.razor +++ b/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayout.razor @@ -1,55 +1,41 @@ @namespace Bit.BlazorUI @inherits BitComponentBase -
- - @{ - var headerHeight = HeaderHeight + StatusBarHeight; - var headerHeightStyle = $"{(headerHeight > 0 ? $"height:{headerHeight}px;" : "")}"; - var headerPaddingStyle = $"{(StatusBarHeight > 0 ? $"padding-top:{StatusBarHeight}px;" : "")}"; - var headerStyles = $"{headerHeightStyle}{headerPaddingStyle}{Styles?.Header}"; - var headerClasses = $"bit-lyt-hdr{(FixedHeader ? " bit-lyt-fhd" : "")} {Classes?.Header}"; - - var mainPaddingTopStyle = $"{(FixedHeader && headerHeight > 0 ? $"padding-top:{headerHeight}px;" : "")}"; - var mainPaddingBottomStyle = $"{(FixedFooter && FooterHeight > 0 ? $"padding-bottom:{FooterHeight}px;" : "")}"; - var mainStyles = $"{mainPaddingTopStyle}{mainPaddingBottomStyle}{Styles?.Main}"; - var mainClasses = $"bit-lyt-man {Classes?.Main}"; - - var footerHeightStyle = $"{(FooterHeight > 0 ? $"height:{FooterHeight}px;" : "")}"; - var footerStyles = $"{footerHeightStyle}{Styles?.Footer}"; - var footerClasses = $"bit-lyt-ftr{(FixedFooter ? " bit-lyt-fft" : "")} {Classes?.Footer}"; - } @if (Header is not null) { -
+
@Header
} -
- @if (NavMenu is not null && HideNavMenu is false) +
+ @if (showNavPanel) { -
- @NavMenu +
+ @NavPanel
} -
+
@Main
@if (Footer is not null) { -
+
@Footer -
+
}
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayout.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayout.razor.cs index e04cf8405a..d732083604 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayout.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayout.razor.cs @@ -7,55 +7,47 @@ public partial class BitLayout : BitComponentBase ///
[Parameter] public BitLayoutClassStyles? Classes { get; set; } - /// - /// Enables fixed positioning of the header at the top of the viewport. - /// - [Parameter] public bool FixedHeader { get; set; } - - /// - /// Enables fixed positioning of the footer at the bottom of the viewport. - /// - [Parameter] public bool FixedFooter { get; set; } - /// /// The content of the footer section. /// [Parameter] public RenderFragment? Footer { get; set; } /// - /// The height of the footer in px to calculate heights and paddings. + /// The content of the header section. /// - [Parameter] public int FooterHeight { get; set; } + [Parameter] public RenderFragment? Header { get; set; } /// - /// The content of the header section. + /// Hides NavPanel content. /// - [Parameter] public RenderFragment? Header { get; set; } + [Parameter] public bool HideNavPanel { get; set; } /// - /// The height of the header in px to calculate heights and paddings. + /// The content of the main section. /// - [Parameter] public int HeaderHeight { get; set; } + [Parameter] public RenderFragment? Main { get; set; } /// - /// Hides NavMenu content when true. + /// The content of the nav panel section. /// - [Parameter] public bool HideNavMenu { get; set; } + [Parameter] public RenderFragment? NavPanel { get; set; } /// - /// The content of the main section. + /// The width of the nav panel section in px. /// - [Parameter] public RenderFragment? Main { get; set; } + [Parameter] public int NavPanelWidth { get; set; } /// - /// The content of the nav-menu section. + /// Enables sticky positioning of the footer at the bottom of the viewport. /// - [Parameter] public RenderFragment? NavMenu { get; set; } + [Parameter, ResetClassBuilder] + public bool StickyFooter { get; set; } /// - /// The height of the status bar on mobile devices to calculate heights and paddings. + /// Enables sticky positioning of the header at the top of the viewport. /// - [Parameter] public int StatusBarHeight { get; set; } + [Parameter, ResetClassBuilder] + public bool StickyHeader { get; set; } /// /// Custom CSS styles for different parts of the BitLayout. @@ -69,6 +61,9 @@ public partial class BitLayout : BitComponentBase protected override void RegisterCssClasses() { ClassBuilder.Register(() => Classes?.Root); + + ClassBuilder.Register(() => StickyHeader ? "bit-lyt-shd" : string.Empty); + ClassBuilder.Register(() => StickyFooter ? "bit-lyt-sft" : string.Empty); } protected override void RegisterCssStyles() diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayout.scss b/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayout.scss index fba6a3e5e0..e9df24de51 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayout.scss +++ b/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayout.scss @@ -15,20 +15,35 @@ } } +.bit-lyt-shd { + height: fit-content; + + > .bit-lyt-hdr { + top: 0; + position: sticky; + z-index: $zindex-base; + } +} + +.bit-lyt-sft { + height: fit-content; + + > .bit-lyt-ftr { + bottom: 0; + position: sticky; + z-index: $zindex-base; + } +} + .bit-lyt-hdr { width: 100%; box-sizing: border-box; } -.bit-lyt-fhd { - top: 0; - position: fixed; - z-index: $zindex-base; -} - .bit-lyt-man { flex-grow: 1; display: flex; + min-height: 100vh; box-sizing: border-box; } @@ -45,9 +60,3 @@ width: 100%; box-sizing: border-box; } - -.bit-lyt-fft { - bottom: 0; - position: fixed; - z-index: $zindex-base; -} diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayoutClassStyles.cs b/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayoutClassStyles.cs index c484c6bbf0..56b62f46f0 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayoutClassStyles.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Layouts/Layout/BitLayoutClassStyles.cs @@ -20,7 +20,7 @@ public class BitLayoutClassStyles /// /// Custom CSS classes/styles for the nav-menu section of the BitLayout. /// - public string? NavMenu { get; set; } + public string? NavPanel { get; set; } /// /// Custom CSS classes/styles for the main-content section of the BitLayout. diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Lists/Carousel/BitCarousel.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Lists/Carousel/BitCarousel.razor.cs index 58f76434b6..cb08373268 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Lists/Carousel/BitCarousel.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Lists/Carousel/BitCarousel.razor.cs @@ -176,7 +176,7 @@ private async Task ResetDimensionsAsync() _othersIndices = Enumerable.Range(0, _internalScrollItemsCount).ToArray(); var itemsCount = _allItems.Count; - var rect = await _js.GetBoundingClientRect(_carousel); + var rect = await _js.BitUtilsGetBoundingClientRect(_carousel); if (rect is null) return; var sign = Dir == BitDir.Rtl ? -1 : 1; for (int i = 0; i < itemsCount; i++) @@ -332,7 +332,7 @@ private async Task HandlePointerMove(MouseEventArgs e) if (Math.Abs(delta) <= 20) return; _isPointerDown = false; - await _js.SetStyle(_carousel, "cursor", ""); + await _js.BitUtilsSetStyle(_carousel, "cursor", ""); if (delta < 0) { @@ -348,14 +348,14 @@ private async Task HandlePointerDown(MouseEventArgs e) { _isPointerDown = true; _pointerX = e.ClientX; - await _js.SetStyle(_carousel, "cursor", "grabbing"); + await _js.BitUtilsSetStyle(_carousel, "cursor", "grabbing"); StateHasChanged(); } private async Task HandlePointerUp(MouseEventArgs e) { _isPointerDown = false; - await _js.SetStyle(_carousel, "cursor", ""); + await _js.BitUtilsSetStyle(_carousel, "cursor", ""); StateHasChanged(); } diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Lists/Swiper/BitSwiper.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Lists/Swiper/BitSwiper.razor.cs index 45fbf37d51..4afd8825bc 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Lists/Swiper/BitSwiper.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Lists/Swiper/BitSwiper.razor.cs @@ -104,7 +104,7 @@ public async Task HandlePointerLeave(double clientX) if (_isPointerDown is false) return; _isPointerDown = false; - await _js.SetStyle(_swiper, "cursor", ""); + await _js.BitUtilsSetStyle(_swiper, "cursor", ""); var time = (DateTime.Now.Ticks - _pointerDownTime) / 10_000; var distance = Math.Abs(clientX - _pointerDownX); @@ -114,7 +114,7 @@ public async Task HandlePointerLeave(double clientX) var swipeSpeed = distance / time; var transitionTime = swipeSpeed > 2 ? 300 : swipeSpeed > 1 ? 600 : 1000; - await _js.SetStyle(_swiper, "transitionDuration", FormattableString.Invariant($"{transitionTime}ms")); + await _js.BitUtilsSetStyle(_swiper, "transitionDuration", FormattableString.Invariant($"{transitionTime}ms")); var x = -(_lastDiffX / Math.Abs(_lastDiffX)) * (_swiperEffectiveWidth * swipeSpeed / 10) + _translateX; await Swipe(x); @@ -192,7 +192,7 @@ private void SetNavigationButtonsVisibility(double translateX) private async Task Go(bool isNext) { await GetDimensions(); - await _js.SetStyle(_swiper, "transitionDuration", ""); + await _js.BitUtilsSetStyle(_swiper, "transitionDuration", ""); var sign = isNext ? -1 : 1; var scrollX = _swiperWidth / _allItems.Count * _internalScrollItemsCount; @@ -235,8 +235,8 @@ private async Task HandlePointerDown(MouseEventArgs e) await GetDimensions(); - await _js.SetStyle(_swiper, "cursor", "grabbing"); - await _js.SetStyle(_swiper, "transitionDuration", ""); + await _js.BitUtilsSetStyle(_swiper, "cursor", "grabbing"); + await _js.BitUtilsSetStyle(_swiper, "transitionDuration", ""); } private async Task HandlePointerUp(MouseEventArgs e) => await HandlePointerLeave(e.ClientX); @@ -256,7 +256,7 @@ private async Task Swipe(double x) if (x < -_swiperEffectiveWidth) x = -_swiperEffectiveWidth; } - await _js.SetStyle(_swiper, "transform", FormattableString.Invariant($"translateX({x}px)")); + await _js.BitUtilsSetStyle(_swiper, "transform", FormattableString.Invariant($"translateX({x}px)")); SetNavigationButtonsVisibility(x); } diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.razor.cs index 21f874b915..d5011048b5 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.razor.cs @@ -597,7 +597,7 @@ private async Task ToggleCallout() { if (IsEnabled is false) return; - await _js.ToggleCallout(_dotnetObj, + await _js.BitCalloutToggleCallout(_dotnetObj, _overflowAnchorId, null, _calloutId, @@ -636,7 +636,7 @@ protected virtual async ValueTask DisposeAsync(bool disposing) try { - await _js.ClearCallout(_calloutId); + await _js.BitCalloutClearCallout(_calloutId); } catch (JSDisconnectedException) { } // we can ignore this exception here } diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.razor.cs index 48f83584e7..b998c9359d 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.razor.cs @@ -150,7 +150,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) if (firstRender is false) return; if (Responsive is false) return; - await _js.SwipesSetup(_calloutId, 0.25m, BitPanelPosition.End, Dir is BitDir.Rtl, _dotnetObj); + await _js.BitSwipesSetup(_calloutId, 0.25m, BitPanelPosition.End, Dir is BitDir.Rtl, _dotnetObj); } @@ -182,7 +182,7 @@ private async Task ToggleCallout() { if (IsEnabled is false) return; - await _js.ToggleCallout(_dotnetObj, + await _js.BitCalloutToggleCallout(_dotnetObj, _Id, null, _calloutId, @@ -236,8 +236,8 @@ protected virtual async ValueTask DisposeAsync(bool disposing) try { - await _js.ClearCallout(_calloutId); - await _js.SwipesDispose(_calloutId); + await _js.BitCalloutClearCallout(_calloutId); + await _js.BitSwipesDispose(_calloutId); } catch (JSDisconnectedException) { } // we can ignore this exception here diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/BitNav.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/BitNav.razor.cs index 70ca783961..acd1178615 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/BitNav.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/BitNav.razor.cs @@ -94,7 +94,7 @@ public partial class BitNav : BitComponentBase, IDisposable where TItem : [Parameter] public int IndentReversedPadding { get; set; } = 4; /// - /// A collection of item to display in the navigation bar. + /// A collection of items to display in the BitNav component. /// [Parameter] [CallOnSet(nameof(OnSetParameters))] @@ -336,6 +336,28 @@ internal List GetChildItems(TItem item) return item.GetValueFromProperty(NameSelectors.CollapseAriaLabel.Name); } + internal object? GetData(TItem item) + { + if (item is BitNavItem navItem) + { + return navItem.Data; + } + + if (item is BitNavOption navOption) + { + return navOption.Data; + } + + if (NameSelectors is null) return null; + + if (NameSelectors.Data.Selector is not null) + { + return NameSelectors.Data.Selector!(item); + } + + return item.GetValueFromProperty(NameSelectors.Data.Name); + } + internal string? GetDescription(TItem item) { if (item is BitNavItem navItem) @@ -862,10 +884,7 @@ private void SetSelectedItemByCurrentUrl() var currentItem = Flatten(_items).FirstOrDefault(item => GetUrl(item) == currentUrl || (GetAdditionalUrls(item)?.Contains(currentUrl) ?? false)); - if (currentItem is not null) - { - _ = AssignSelectedItem(currentItem); - } + _ = AssignSelectedItem(currentItem); } private void SetIsExpanded(TItem item, bool value) diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.razor.cs index d75894e18f..3fd80c28b4 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.razor.cs @@ -211,10 +211,7 @@ private void SetSelectedItemByCurrentUrl() var currentItem = _items.FirstOrDefault(item => string.Equals(GetUrl(item), currentUrl, StringComparison.OrdinalIgnoreCase) || (GetAdditionalUrls(item)?.Any(u => string.Equals(u, currentUrl, StringComparison.OrdinalIgnoreCase)) ?? false)); - if (currentItem is not null) - { - _ = AssignSelectedItem(currentItem); - } + _ = AssignSelectedItem(currentItem); } private void OnSetParameters() diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Callout/BitCallout.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Callout/BitCallout.razor.cs index 3322053a1d..5ebd497af5 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Callout/BitCallout.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Callout/BitCallout.razor.cs @@ -145,7 +145,7 @@ private async Task ToggleCallout() var id = Anchor is not null ? _anchorId : AnchorId ?? _Id; - await _js.ToggleCallout(_dotnetObj, + await _js.BitCalloutToggleCallout(_dotnetObj, id, AnchorEl is null ? null : AnchorEl(), _contentId, @@ -181,7 +181,7 @@ protected virtual async ValueTask DisposeAsync(bool disposing) try { - await _js.ClearCallout(_contentId); + await _js.BitCalloutClearCallout(_contentId); } catch (JSDisconnectedException) { } // we can ignore this exception here } diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Dialog/BitDialog.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Dialog/BitDialog.razor.cs index 5ae699aba7..0db768becd 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Dialog/BitDialog.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Dialog/BitDialog.razor.cs @@ -164,7 +164,7 @@ public partial class BitDialog : BitComponentBase, IAsyncDisposable { await InvokeAsync(async () => { - _ = _js.ToggleOverflow(ScrollerSelector, true); + _ = _js.BitUtilsToggleOverflow(ScrollerSelector, true); Result = null; @@ -233,7 +233,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) if (AutoToggleScroll is false) return; - _offsetTop = await _js.ToggleOverflow(ScrollerSelector, IsOpen); + _offsetTop = await _js.BitUtilsToggleOverflow(ScrollerSelector, IsOpen); if (AbsolutePosition is false) return; diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Modal/BitModal.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Modal/BitModal.razor.cs index c19d8f49bb..5726c19c14 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Modal/BitModal.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Modal/BitModal.razor.cs @@ -232,7 +232,7 @@ private async Task ToggleScroll(bool isOpen) { if (ModalParameters.AutoToggleScroll is false) return; - _offsetTop = await _js.ToggleOverflow(ModalParameters.ScrollerSelector ?? "body", isOpen); + _offsetTop = await _js.BitUtilsToggleOverflow(ModalParameters.ScrollerSelector ?? "body", isOpen); } diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.razor.cs index 6f6863e164..20607a18ae 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.razor.cs @@ -165,7 +165,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) if (firstRender) { var dotnetObj = DotNetObjectReference.Create(this); - await _js.SwipesSetup(_containerId, SwipeTrigger ?? 0.25m, Position ?? BitPanelPosition.End, Dir == BitDir.Rtl, dotnetObj, false); + await _js.BitSwipesSetup(_containerId, SwipeTrigger ?? 0.25m, Position ?? BitPanelPosition.End, Dir == BitDir.Rtl, dotnetObj, false); } if (_internalIsOpen == IsOpen) return; @@ -176,7 +176,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) if (AutoToggleScroll is false) return; - _offsetTop = await _js.ToggleOverflow(ScrollerSelector ?? "body", IsOpen); + _offsetTop = await _js.BitUtilsToggleOverflow(ScrollerSelector ?? "body", IsOpen); StyleBuilder.Reset(); StateHasChanged(); @@ -258,7 +258,7 @@ protected virtual async ValueTask DisposeAsync(bool disposing) try { - await _js.SwipesDispose(_containerId); + await _js.BitSwipesDispose(_containerId); } catch (JSDisconnectedException) { } // we can ignore this exception here diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.razor.cs index 3ffb63375f..4c5c02d762 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.razor.cs @@ -73,7 +73,7 @@ private async Task ScrollIntoView() { if (IsEnabled is false) return; - await _js.ScrollElementIntoView(Href![1..]); + await _js.BitUtilsScrollElementIntoView(Href![1..]); } private void OnSetHrefAndRel() diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Utilities/SwipeTrap/BitSwipeTrap.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Utilities/SwipeTrap/BitSwipeTrap.razor.cs index 4e9212f319..0d5ab57b97 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Utilities/SwipeTrap/BitSwipeTrap.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Utilities/SwipeTrap/BitSwipeTrap.razor.cs @@ -93,7 +93,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) if (firstRender) { var dotnetObj = DotNetObjectReference.Create(this); - await _js.BitSwipeTrapSetup(UniqueId, RootElement, Trigger ?? 0.25m, Threshold ?? 0, Throttle ?? 10, dotnetObj); + await _js.BitSwipeTrapSetup(UniqueId, RootElement, Trigger ?? 0.25m, Threshold ?? 0, Throttle ?? 0, dotnetObj); } await base.OnAfterRenderAsync(firstRender); diff --git a/src/BlazorUI/Bit.BlazorUI/Extensions/JsInterop/CalloutsJsRuntimeExtensions.cs b/src/BlazorUI/Bit.BlazorUI/Extensions/JsInterop/CalloutsJsRuntimeExtensions.cs index 3ed0cf856a..3960864f3f 100644 --- a/src/BlazorUI/Bit.BlazorUI/Extensions/JsInterop/CalloutsJsRuntimeExtensions.cs +++ b/src/BlazorUI/Bit.BlazorUI/Extensions/JsInterop/CalloutsJsRuntimeExtensions.cs @@ -4,7 +4,7 @@ namespace Bit.BlazorUI; internal static class CalloutsJsRuntimeExtensions { - internal static ValueTask ToggleCallout<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>( + internal static ValueTask BitCalloutToggleCallout<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>( this IJSRuntime jsRuntime, DotNetObjectReference dotnetObj, string componentId, @@ -40,7 +40,7 @@ internal static class CalloutsJsRuntimeExtensions maxWidth); } - internal static ValueTask ClearCallout(this IJSRuntime jsRuntime, string calloutId) + internal static ValueTask BitCalloutClearCallout(this IJSRuntime jsRuntime, string calloutId) { return jsRuntime.InvokeVoid("BitBlazorUI.Callouts.clear", calloutId); } diff --git a/src/BlazorUI/Bit.BlazorUI/Extensions/JsInterop/SwipesJsRuntimeExtensions.cs b/src/BlazorUI/Bit.BlazorUI/Extensions/JsInterop/SwipesJsRuntimeExtensions.cs index d0dce6f787..9f5e1ec16d 100644 --- a/src/BlazorUI/Bit.BlazorUI/Extensions/JsInterop/SwipesJsRuntimeExtensions.cs +++ b/src/BlazorUI/Bit.BlazorUI/Extensions/JsInterop/SwipesJsRuntimeExtensions.cs @@ -4,7 +4,7 @@ namespace Bit.BlazorUI; internal static class SwipesJsRuntimeExtensions { - internal static ValueTask SwipesSetup<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(this IJSRuntime js, + internal static ValueTask BitSwipesSetup<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(this IJSRuntime js, string id, decimal trigger, BitPanelPosition position, @@ -15,7 +15,7 @@ internal static class SwipesJsRuntimeExtensions return js.InvokeVoid("BitBlazorUI.Swipes.setup", id, trigger, position, isRtl, dotnetObj, isResponsive); } - internal static ValueTask SwipesDispose(this IJSRuntime jsRuntime, string id) + internal static ValueTask BitSwipesDispose(this IJSRuntime jsRuntime, string id) { return jsRuntime.InvokeVoid("BitBlazorUI.Swipes.dispose", id); } diff --git a/src/BlazorUI/Bit.BlazorUI/Extensions/JsInterop/UtilsJsRuntimeExtensions.cs b/src/BlazorUI/Bit.BlazorUI/Extensions/JsInterop/UtilsJsRuntimeExtensions.cs index 8a430ff51d..30479a1428 100644 --- a/src/BlazorUI/Bit.BlazorUI/Extensions/JsInterop/UtilsJsRuntimeExtensions.cs +++ b/src/BlazorUI/Bit.BlazorUI/Extensions/JsInterop/UtilsJsRuntimeExtensions.cs @@ -2,49 +2,49 @@ internal static class UtilsJsRuntimeExtensions { - internal static ValueTask GetBodyWidth(this IJSRuntime jsRuntime) + internal static ValueTask BitUtilsGetBodyWidth(this IJSRuntime jsRuntime) { return jsRuntime.Invoke("BitBlazorUI.Utils.getBodyWidth"); } - internal static ValueTask SetProperty(this IJSRuntime jsRuntime, ElementReference element, string property, object value) + internal static ValueTask BitUtilsSetProperty(this IJSRuntime jsRuntime, ElementReference element, string property, object? value) { return jsRuntime.InvokeVoid("BitBlazorUI.Utils.setProperty", element, property, value); } - internal static ValueTask GetProperty(this IJSRuntime jsRuntime, ElementReference element, string property) + internal static ValueTask BitUtilsGetProperty(this IJSRuntime jsRuntime, ElementReference element, string property) { return jsRuntime.Invoke("BitBlazorUI.Utils.getProperty", element, property); } - internal static ValueTask GetBoundingClientRect(this IJSRuntime jsRuntime, ElementReference element) + internal static ValueTask BitUtilsGetBoundingClientRect(this IJSRuntime jsRuntime, ElementReference element) { return jsRuntime.Invoke("BitBlazorUI.Utils.getBoundingClientRect", element); } - internal static ValueTask ScrollElementIntoView(this IJSRuntime jsRuntime, string targetElementId) + internal static ValueTask BitUtilsScrollElementIntoView(this IJSRuntime jsRuntime, string targetElementId) { return jsRuntime.InvokeVoid("BitBlazorUI.Utils.scrollElementIntoView", targetElementId); } - internal static ValueTask SelectText(this IJSRuntime jsRuntime, ElementReference element) + internal static ValueTask BitUtilsSelectText(this IJSRuntime jsRuntime, ElementReference element) { return jsRuntime.InvokeVoid("BitBlazorUI.Utils.selectText", element); } - internal static ValueTask SetStyle(this IJSRuntime jsRuntime, ElementReference element, string key, string value) + internal static ValueTask BitUtilsSetStyle(this IJSRuntime jsRuntime, ElementReference element, string key, string value) { return jsRuntime.InvokeVoid("BitBlazorUI.Utils.setStyle", element, key, value); } - internal static ValueTask ToggleOverflow(this IJSRuntime jsRuntime, string scrollerSelector, bool isHidden) + internal static ValueTask BitUtilsToggleOverflow(this IJSRuntime jsRuntime, string scrollerSelector, bool isHidden) { return jsRuntime.Invoke("BitBlazorUI.Utils.toggleOverflow", scrollerSelector, isHidden); } diff --git a/src/BlazorUI/Bit.BlazorUI/Extensions/StringExtensions.cs b/src/BlazorUI/Bit.BlazorUI/Extensions/StringExtensions.cs index 4fb33a2584..8dcc5ff61c 100644 --- a/src/BlazorUI/Bit.BlazorUI/Extensions/StringExtensions.cs +++ b/src/BlazorUI/Bit.BlazorUI/Extensions/StringExtensions.cs @@ -1,4 +1,5 @@ -namespace Bit.BlazorUI; +#nullable enable +namespace Bit.BlazorUI; internal static class StringExtensions { diff --git a/src/BlazorUI/Bit.BlazorUI/Scripts/general.ts b/src/BlazorUI/Bit.BlazorUI/Scripts/general.ts index 439d021720..8b3488d591 100644 --- a/src/BlazorUI/Bit.BlazorUI/Scripts/general.ts +++ b/src/BlazorUI/Bit.BlazorUI/Scripts/general.ts @@ -1,4 +1,4 @@ -(BitBlazorUI as any).version = (window as any)['bit-blazorui version'] = '9.1.2'; +(BitBlazorUI as any).version = (window as any)['bit-blazorui version'] = '9.2.0'; interface DotNetObject { invokeMethod(methodIdentifier: string, ...args: any[]): T; diff --git a/src/BlazorUI/Bit.BlazorUI/Styles/media-queries.scss b/src/BlazorUI/Bit.BlazorUI/Styles/media-queries.scss index b6f178a6c5..c1628fe3f8 100644 --- a/src/BlazorUI/Bit.BlazorUI/Styles/media-queries.scss +++ b/src/BlazorUI/Bit.BlazorUI/Styles/media-queries.scss @@ -1,3 +1,5 @@ +// https://github.com/Necromancerx/media-queries-scss-mixins + $brk-xs-max: 600px; $brk-sm-min: 601px; $brk-sm-max: 960px; diff --git a/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Bit.BlazorUI.Demo.Server.csproj b/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Bit.BlazorUI.Demo.Server.csproj index a0b7a01a85..7a31606a92 100644 --- a/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Bit.BlazorUI.Demo.Server.csproj +++ b/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Bit.BlazorUI.Demo.Server.csproj @@ -5,21 +5,21 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + + diff --git a/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Components/App.razor b/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Components/App.razor index 97d974449b..a67e1c5f7b 100644 --- a/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Components/App.razor +++ b/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Components/App.razor @@ -13,8 +13,15 @@ - + + + + @@ -47,9 +54,9 @@ Microsoft Clarity --> + - diff --git a/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Bit.BlazorUI.Demo.Shared.csproj b/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Bit.BlazorUI.Demo.Shared.csproj index 2ec56da0bd..918454cdc4 100644 --- a/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Bit.BlazorUI.Demo.Shared.csproj +++ b/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Bit.BlazorUI.Demo.Shared.csproj @@ -5,11 +5,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Bit.BlazorUI.Demo.Client.Core.csproj b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Bit.BlazorUI.Demo.Client.Core.csproj index 8f446710aa..dfa709cee2 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Bit.BlazorUI.Demo.Client.Core.csproj +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Bit.BlazorUI.Demo.Client.Core.csproj @@ -16,11 +16,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Components/ComponentExampleBox.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Components/ComponentExampleBox.razor index dd473865ca..f8a69fc59a 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Components/ComponentExampleBox.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Components/ComponentExampleBox.razor @@ -3,25 +3,28 @@
@Title -
- - @(showCode ? "Hide code" : "Show code") - - - @if (isLinkCopied) - { - @copyLinkMessage - } - -
+ @if (RazorCode is not null || CsharpCode is not null) + { +
+ + @(showCode ? "Hide code" : "Show code") + + + @if (isLinkCopied) + { + @copyLinkMessage + } + +
+ }
@@ -39,14 +42,18 @@
-                @RazorCode.Trim()
+                
+                
+                    @RazorCode?.Trim()
+                
 
                 @if (CsharpCode.HasValue())
                 {
                     
 @code {
-     @CsharpCode.Trim().Replace("\n", "\n     ")
-}
+    @CsharpCode?.Trim().Replace("\n", "\n     ")
+}
+                    
                 }
             
} diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Extensions/IJSRuntimeExtensions.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Extensions/IJSRuntimeExtensions.cs index 5037428723..288c56a267 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Extensions/IJSRuntimeExtensions.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Extensions/IJSRuntimeExtensions.cs @@ -2,11 +2,6 @@ public static class IJSRuntimeExtensions { - public static async Task ToggleBodyOverflow(this IJSRuntime jsRuntime, bool isNavOpen) - { - await jsRuntime.InvokeVoidAsync("toggleBodyOverflow", isNavOpen); - } - public static async Task ScrollToElement(this IJSRuntime jsRuntime, string targetElementId) { await jsRuntime.InvokeVoidAsync("scrollToElement", targetElementId); diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Extensions/IServiceCollectionExtensions.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Extensions/IServiceCollectionExtensions.cs index e0e28c4ada..f10c87d4b4 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Extensions/IServiceCollectionExtensions.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Extensions/IServiceCollectionExtensions.cs @@ -21,7 +21,6 @@ public static IServiceCollection AddClientSharedServices(this IServiceCollection services.TryAddTransient(); services.TryAddTransient(); - services.TryAddScoped(); services.AddBitBlazorUIServices(); services.AddBitBlazorUIExtrasServices(trySingleton: AppRenderMode.IsBlazorHybrid); diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/BitActionButtonDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/BitActionButtonDemo.razor index 8f134e5109..f7fbfdf567 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/BitActionButtonDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/BitActionButtonDemo.razor @@ -239,27 +239,4 @@
- - -@code { - private bool formIsValidSubmit; - private ButtonValidationModel buttonValidationModel = new(); - - private async Task HandleValidSubmit() - { - formIsValidSubmit = true; - - await Task.Delay(2000); - - buttonValidationModel = new(); - - formIsValidSubmit = false; - - StateHasChanged(); - } - - private void HandleInvalidSubmit() - { - formIsValidSubmit = false; - } -} \ No newline at end of file + \ No newline at end of file diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/BitActionButtonDemo.razor.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/BitActionButtonDemo.razor.cs index 9c4b43558f..302cb210aa 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/BitActionButtonDemo.razor.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/BitActionButtonDemo.razor.cs @@ -431,4 +431,27 @@ public partial class BitActionButtonDemo ] }, ]; + + + + private bool formIsValidSubmit; + private ButtonValidationModel buttonValidationModel = new(); + + private async Task HandleValidSubmit() + { + formIsValidSubmit = true; + + await Task.Delay(2000); + + buttonValidationModel = new(); + + formIsValidSubmit = false; + + StateHasChanged(); + } + + private void HandleInvalidSubmit() + { + formIsValidSubmit = false; + } } diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.cs index c4b9b4d2d7..698761d93b 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.cs @@ -19,6 +19,15 @@ public partial class BitButtonGroupDemo Description = "Determines that only the icon should be rendered.", }, new() + { + Name = "Classes", + Type = "BitButtonGroupClassStyles?", + DefaultValue = "null", + Description = "Custom CSS classes for different parts of the ButtonGroup.", + LinkType = LinkType.Link, + Href = "#class-styles", + }, + new() { Name = "Color", Type = "BitColor?", @@ -28,6 +37,13 @@ public partial class BitButtonGroupDemo Href = "#color-enum", }, new() + { + Name = "FullWidth", + Type = "bool", + DefaultValue = "false", + Description = "Expand the ButtonGroup width to 100% of the available width.", + }, + new() { Name = "Items", Type = "IEnumerable", @@ -67,7 +83,7 @@ public partial class BitButtonGroupDemo }, new() { - Name = "Toggled", + Name = "Toggle", Type = "bool", DefaultValue = "false", Description = "Display ButtonGroup with toggle mode enabled for each button.", @@ -82,6 +98,15 @@ public partial class BitButtonGroupDemo Href = "#button-size-enum", }, new() + { + Name = "Styles", + Type = "BitButtonGroupClassStyles?", + DefaultValue = "null", + Description = "Custom CSS styles for different parts of the ButtonGroup.", + LinkType = LinkType.Link, + Href = "#class-styles", + }, + new() { Name = "Variant", Type = "BitVariant?", @@ -342,6 +367,49 @@ public partial class BitButtonGroupDemo ] }, new() + { + Id = "class-styles", + Title = "BitButtonGroupClassStyles", + Parameters = + [ + new() + { + Name = "Root", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the root element of the BitButtonGroup.", + }, + new() + { + Name = "Button", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the internal button of the BitButtonGroup.", + }, + new() + { + Name = "Icon", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the icon of the BitButtonGroup." + }, + new() + { + Name = "Text", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the text of the BitButtonGroup." + }, + new() + { + Name = "ToggledButton", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the button when in toggle mode of the BitButtonGroup.", + }, + ], + }, + new() { Id = "name-selectors", Title = "BitButtonGroupNameSelectors", diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scss b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scss index d477618eb1..daf5d6992e 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scss +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scss @@ -26,4 +26,10 @@ color: peachpuff; background-color: tomato; } + + .custom-btn { + color: aliceblue; + border-color: aliceblue; + background-color: crimson; + } } diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor index 8552384e10..f382d7a534 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor @@ -33,134 +33,7 @@ - - -
Offering a range of specialized colors, providing visual cues for specific states within your application.
-

-
-
Primary
- - - -
-

-
-
Secondary
- - - -
-

-
-
Tertiary
- - - -
-

-
-
Info
- - - -
-

-
-
Success
- - - -
-

-
-
Warning
- - - -
-

-
-
SevereWarning
- - - -
-

-
-
Error
- - - -
-

-
-
-
PrimaryBackground
- - - -
-

-
-
SecondaryBackground
- - - -
-

-
-
TertiaryBackground
- - - -
-
-

-
-
PrimaryForeground
- - - -
-

-
-
SecondaryForeground
- - - -
-

-
-
TertiaryForeground
- - - -
-

-
-
PrimaryBorder
- - - -
-

-
-
SecondaryBorder
- - - -
-

-
-
TertiaryBorder
- - - -
-
-
- - +
Each item in the ButtonGroup can have an icon.


@@ -187,7 +60,7 @@
- +
The IconOnly allows buttons to display only icons without any text, ideal for minimalistic designs or limited space.


@@ -237,7 +110,7 @@
- +
Reverses the positions of the icon and the main content of the button.


@@ -267,49 +140,55 @@
- + -
The Toggled in BitButtonGroup allows you to control the active or inactive state of each button, providing clear visual feedback to users about which buttons are selected or currently in use.
+
The Toggle in BitButtonGroup allows you to control the active or inactive state of each button, providing clear visual feedback to users about which buttons are selected or currently in use.


Fill (default)
- + ReversedIcon = { Selector = i => i.ReversedIcon } })" />


Outline
- + ReversedIcon = { Selector = i => i.ReversedIcon } })" />


Text
- + ReversedIcon = { Selector = i => i.ReversedIcon } })" />
- +
By default the BitButtonGroup component is horizontal, but can be turned vertical by adding the Vertical property.


@@ -332,6 +211,29 @@
+ + +
Managing button click events.
+

+
+
Component's ItemClick event:
+ +
Clicked item: @clickedCustom
+
+

+
+
Item's Click event:
+ +
Click count: @clickCounter
+
+
+
+
Different sizes for buttons to meet design needs, ensuring flexibility within your application.
@@ -359,7 +261,146 @@
- + + +
Setting the FullWidth makes the button group occupy 100% of its container's width.
+

+
+ + + +
+
+
+ + + +
Offering a range of specialized colors, providing visual cues for specific states within your application.
+

+
+
Primary
+ + + +
+

+
+
Secondary
+ + + +
+

+
+
Tertiary
+ + + +
+

+
+
Info
+ + + +
+

+
+
Success
+ + + +
+

+
+
Warning
+ + + +
+

+
+
SevereWarning
+ + + +
+

+
+
Error
+ + + +
+

+
+
+
PrimaryBackground
+ + + +
+

+
+
SecondaryBackground
+ + + +
+

+
+
TertiaryBackground
+ + + +
+
+

+
+
PrimaryForeground
+ + + +
+

+
+
SecondaryForeground
+ + + +
+

+
+
TertiaryForeground
+ + + +
+

+
+
PrimaryBorder
+ + + +
+

+
+
SecondaryBorder
+ + + +
+

+
+
TertiaryBorder
+ + + +
+
+
+ +
Empower customization by overriding default styles and classes, allowing tailored design modifications to suit specific UI requirements.


@@ -376,33 +417,23 @@ NameSelectors="@(new() { Text = { Selector = i => i.Name }, IconName = { Selector = i => i.Icon } })" />
- - - - - -
Managing button click events.


-
Component's ItemClick event:
+
Styles & Classes:
-
Clicked item: @clickedCustom
-
-

-
-
Item's Click event:
- -
Click count: @clickCounter
+ Styles="@(new() { Button = "color: darkcyan; border-color: deepskyblue; background-color: azure;" })" /> + +
- +
Use BitButtonGroup in right-to-left (RTL).

diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.cs index 0369b8eb8c..b8528799dc 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.cs @@ -40,9 +40,9 @@ public partial class _BitButtonGroupCustomDemo private List toggledCustoms = [ - new() { OnName = "Back (2X)", OffName = "Back", OnIcon = BitIconName.RewindTwoX, OffIcon = BitIconName.Rewind }, + new() { OnName = "Back (2X)", OffName = "Back (1X)", OnIcon = BitIconName.RewindTwoX, OffIcon = BitIconName.Rewind }, new() { OnTitle = "Resume", OffTitle = "Play", OnIcon = BitIconName.PlayResume, OffIcon = BitIconName.Play }, - new() { OnName = "Forward (2X)", OffName = "Forward", OnIcon = BitIconName.FastForwardTwoX, OffIcon = BitIconName.FastForward, ReversedIcon = true } + new() { OnName = "Forward (2X)", OffName = "Forward (1X)", OnIcon = BitIconName.FastForwardTwoX, OffIcon = BitIconName.FastForward, ReversedIcon = true } ]; private List eventsCustoms = diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cs index 76886dd07e..ef5dcaa1e1 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cs @@ -49,90 +49,6 @@ public class Operation ];"; private readonly string example3RazorCode = @" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"; - private readonly string example3CsharpCode = @" -private BitButtonGroupNameSelectors nameSelector = new() { Text = { Selector = i => i.Name } }; - -public class Operation -{ - public string? Name { get; set; } -} - -private List basicCustoms = -[ - new() { Name = ""Add"" }, new() { Name = ""Edit"" }, new() { Name = ""Delete"" } -];"; - - private readonly string example4RazorCode = @" i.Name }, IconName = { Selector = i => i.Icon } })"" /> @@ -144,7 +60,7 @@ public class Operation i.Name }, IconName = { Selector = i => i.Icon } })"" />"; - private readonly string example4CsharpCode = @" + private readonly string example3CsharpCode = @" public class Operation { public string? Name { get; set; } @@ -158,7 +74,7 @@ public class Operation new() { Name = ""Delete"", Icon = BitIconName.Delete } ];"; - private readonly string example5RazorCode = @" + private readonly string example4RazorCode = @" i.Name }, IconName = { Selector = i => i.Icon } })"" IconOnly /> @@ -183,7 +99,7 @@ public class Operation i.Name }, IconName = { Selector = i => i.Icon } })"" />"; - private readonly string example5CsharpCode = @" + private readonly string example4CsharpCode = @" public class Operation { public string? Name { get; set; } @@ -204,7 +120,7 @@ public class Operation new() { Name = ""Delete"", Icon = BitIconName.Delete } ];"; - private readonly string example6RazorCode = @" + private readonly string example5RazorCode = @" i.Name }, IconName = { Selector = i => i.Icon }, @@ -219,7 +135,7 @@ public class Operation NameSelectors=""@(new() { Text = { Selector = i => i.Name }, IconName = { Selector = i => i.Icon }, ReversedIcon = { Selector = i => i.ReversedIcon } })"" />"; - private readonly string example6CsharpCode = @" + private readonly string example5CsharpCode = @" public class Operation { public string? Name { get; set; } @@ -234,34 +150,40 @@ public class Operation new() { Name = ""Delete"", Icon = BitIconName.Delete, ReversedIcon = true } ];"; - private readonly string example7RazorCode = @" - i.OnName }, OffText = { Selector = i => i.OffName }, OnTitle = { Selector = i => i.OnTitle }, OffTitle = { Selector = i => i.OffTitle }, OnIconName = { Selector = i => i.OnIcon }, OffIconName = { Selector = i => i.OffIcon }, - ReversedIcon = { Selector = i => i.ReversedIcon } })"" Toggled /> + ReversedIcon = { Selector = i => i.ReversedIcon } })"" /> - i.OnName }, OffText = { Selector = i => i.OffName }, OnTitle = { Selector = i => i.OnTitle }, OffTitle = { Selector = i => i.OffTitle }, OnIconName = { Selector = i => i.OnIcon }, OffIconName = { Selector = i => i.OffIcon }, - ReversedIcon = { Selector = i => i.ReversedIcon } })"" Toggled /> + ReversedIcon = { Selector = i => i.ReversedIcon } })"" /> - i.OnName }, OffText = { Selector = i => i.OffName }, OnTitle = { Selector = i => i.OnTitle }, OffTitle = { Selector = i => i.OffTitle }, OnIconName = { Selector = i => i.OnIcon }, OffIconName = { Selector = i => i.OffIcon }, - ReversedIcon = { Selector = i => i.ReversedIcon } })"" Toggled />"; - private readonly string example7CsharpCode = @" + ReversedIcon = { Selector = i => i.ReversedIcon } })"" />"; + private readonly string example6CsharpCode = @" public class Operation { public string? OnIcon { get; set; } @@ -275,16 +197,16 @@ public class Operation private List toggledCustoms = [ - new() { OnName = ""Back (2X)"", OffName = ""Back"", OnIcon = BitIconName.RewindTwoX, OffIcon = BitIconName.Rewind }, + new() { OnName = ""Back (2X)"", OffName = ""Back (1X)"", OnIcon = BitIconName.RewindTwoX, OffIcon = BitIconName.Rewind }, new() { OnTitle = ""Resume"", OffTitle = ""Play"", OnIcon = BitIconName.PlayResume, OffIcon = BitIconName.Play }, - new() { OnName = ""Forward (2X)"", OffName = ""Forward"", OnIcon = BitIconName.FastForwardTwoX, OffIcon = BitIconName.FastForward, ReversedIcon = true } + new() { OnName = ""Forward (2X)"", OffName = ""Forward (1X)"", OnIcon = BitIconName.FastForwardTwoX, OffIcon = BitIconName.FastForward, ReversedIcon = true } ];"; - private readonly string example8RazorCode = @" + private readonly string example7RazorCode = @" "; - private readonly string example8CsharpCode = @" + private readonly string example7CsharpCode = @" private BitButtonGroupNameSelectors nameSelector = new() { Text = { Selector = i => i.Name } }; public class Operation @@ -297,6 +219,48 @@ public class Operation new() { Name = ""Add"" }, new() { Name = ""Edit"" }, new() { Name = ""Delete"" } ];"; + private readonly string example8RazorCode = @" + clickedCustom = item.Name"" /> +
Clicked item: @clickedCustom
+ + i.Name }, + IconName = { Selector = i => i.Icon }, + OnClick = { Selector = i => i.Clicked } })"" /> +
Click count: @clickCounter
"; + private readonly string example8CsharpCode = @" +private BitButtonGroupNameSelectors nameSelector = new() { Text = { Selector = i => i.Name } }; + +public class Operation +{ + public string? Name { get; set; } + public string? Icon { get; set; } + public Action? Clicked { get; set; } +} + +private int clickCounter; + +private List basicCustoms = +[ + new() { Name = ""Add"" }, new() { Name = ""Edit"" }, new() { Name = ""Delete"" } +]; + +private List eventsCustoms = +[ + new() { Name = ""Increase"", Icon = BitIconName.Add }, + new() { Name = ""Reset"", Icon = BitIconName.Reset }, + new() { Name = ""Decrease"", Icon = BitIconName.Remove } +]; + +protected override void OnInitialized() +{ + eventsCustoms[0].Clicked = _ => { clickCounter++; StateHasChanged(); }; + eventsCustoms[1].Clicked = _ => { clickCounter = 0; StateHasChanged(); }; + eventsCustoms[2].Clicked = _ => { clickCounter--; StateHasChanged(); }; +}"; + private readonly string example9RazorCode = @" @@ -323,6 +287,107 @@ public class Operation ];"; private readonly string example10RazorCode = @" + + +"; + private readonly string example10CsharpCode = @" +private BitButtonGroupNameSelectors nameSelector = new() { Text = { Selector = i => i.Name } }; + +public class Operation +{ + public string? Name { get; set; } +} + +private List basicCustoms = +[ + new() { Name = ""Add"" }, new() { Name = ""Edit"" }, new() { Name = ""Delete"" } +];"; + + private readonly string example11RazorCode = @" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +"; + private readonly string example11CsharpCode = @" +private BitButtonGroupNameSelectors nameSelector = new() { Text = { Selector = i => i.Name } }; + +public class Operation +{ + public string? Name { get; set; } +} + +private List basicCustoms = +[ + new() { Name = ""Add"" }, new() { Name = ""Edit"" }, new() { Name = ""Delete"" } +];"; + + private readonly string example12RazorCode = @" @@ -354,8 +425,18 @@ public class Operation i.Name }, - IconName = { Selector = i => i.Icon } })"" />"; - private readonly string example10CsharpCode = @" + IconName = { Selector = i => i.Icon } })"" /> + + + +"; + private readonly string example12CsharpCode = @" private BitButtonGroupNameSelectors nameSelector = new() { Text = { Selector = i => i.Name } }; public class Operation @@ -387,49 +468,7 @@ public class Operation } ];"; - private readonly string example11RazorCode = @" - clickedCustom = item.Name"" /> -
Clicked item: @clickedCustom
- - i.Name }, - IconName = { Selector = i => i.Icon }, - OnClick = { Selector = i => i.Clicked } })"" /> -
Click count: @clickCounter
"; - private readonly string example11CsharpCode = @" -private BitButtonGroupNameSelectors nameSelector = new() { Text = { Selector = i => i.Name } }; - -public class Operation -{ - public string? Name { get; set; } - public string? Icon { get; set; } - public Action? Clicked { get; set; } -} - -private int clickCounter; - -private List basicCustoms = -[ - new() { Name = ""Add"" }, new() { Name = ""Edit"" }, new() { Name = ""Delete"" } -]; - -private List eventsCustoms = -[ - new() { Name = ""Increase"", Icon = BitIconName.Add }, - new() { Name = ""Reset"", Icon = BitIconName.Reset }, - new() { Name = ""Decrease"", Icon = BitIconName.Remove } -]; - -protected override void OnInitialized() -{ - eventsCustoms[0].Clicked = _ => { clickCounter++; StateHasChanged(); }; - eventsCustoms[1].Clicked = _ => { clickCounter = 0; StateHasChanged(); }; - eventsCustoms[2].Clicked = _ => { clickCounter--; StateHasChanged(); }; -}"; - - private readonly string example12RazorCode = @" + private readonly string example13RazorCode = @" i.Name }, IconName = { Selector = i => i.Icon } })"" />"; - private readonly string example12CsharpCode = @" + private readonly string example13CsharpCode = @" public class Operation { public string? Name { get; set; } diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor index f8988ea109..95ebf92504 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor @@ -33,134 +33,7 @@
- - -
Offering a range of specialized colors, providing visual cues for specific states within your application.
-

-
-
Primary
- - - -
-

-
-
Secondary
- - - -
-

-
-
Tertiary
- - - -
-

-
-
Info
- - - -
-

-
-
Success
- - - -
-

-
-
Warning
- - - -
-

-
-
SevereWarning
- - - -
-

-
-
Error
- - - -
-

-
-
-
PrimaryBackground
- - - -
-

-
-
SecondaryBackground
- - - -
-

-
-
TertiaryBackground
- - - -
-
-

-
-
PrimaryForeground
- - - -
-

-
-
SecondaryForeground
- - - -
-

-
-
TertiaryForeground
- - - -
-

-
-
PrimaryBorder
- - - -
-

-
-
SecondaryBorder
- - - -
-

-
-
TertiaryBorder
- - - -
-
-
- - +
Each item in the ButtonGroup can have an icon.


@@ -181,7 +54,7 @@
- +
The IconOnly allows buttons to display only icons without any text, ideal for minimalistic designs or limited space.


@@ -219,7 +92,7 @@
- +
Reverses the positions of the icon and the main content of the button.


@@ -240,28 +113,28 @@
- + -
The Toggled in BitButtonGroup allows you to control the active or inactive state of each button, providing clear visual feedback to users about which buttons are selected or currently in use.
+
The Toggle in BitButtonGroup allows you to control the active or inactive state of each button, providing clear visual feedback to users about which buttons are selected or currently in use.


Fill (default)
- +


Outline
- +


Text
- +
- +
By default the BitButtonGroup component is horizontal, but can be turned vertical by adding the Vertical property.


@@ -284,6 +157,24 @@
+ + +
Managing button click events.
+

+
+
Component's ItemClick event:
+ +
Clicked item: @clickedItem
+
+

+
+
Item's Click event:
+ +
Click count: @clickCounter
+
+
+
+
Different sizes for buttons to meet design needs, ensuring flexibility within your application.
@@ -311,42 +202,174 @@
- + -
Empower customization by overriding default styles and classes, allowing tailored design modifications to suit specific UI requirements.
+
Setting the FullWidth makes the button group occupy 100% of its container's width.


-
Component's style & class:
- - + + +
+
+
+ + + +
Offering a range of specialized colors, providing visual cues for specific states within your application.


-
Item's style & class:
- +
Primary
+ + + +
+

+
+
Secondary
+ + + +
+

+
+
Tertiary
+ + + +
+

+
+
Info
+ + + +
+

+
+
Success
+ + + +
+

+
+
Warning
+ + + +
+

+
+
SevereWarning
+ + + +
+

+
+
Error
+ + + +
+

+
+
+
PrimaryBackground
+ + + +
+

+
+
SecondaryBackground
+ + + +
+

+
+
TertiaryBackground
+ + + +
+
+

+
+
PrimaryForeground
+ + + +
+

+
+
SecondaryForeground
+ + + +
+

+
+
TertiaryForeground
+ + + +
+

+
+
PrimaryBorder
+ + + +
+

+
+
SecondaryBorder
+ + + +
+

+
+
TertiaryBorder
+ + +
- + -
Managing button click events.
+
Empower customization by overriding default styles and classes, allowing tailored design modifications to suit specific UI requirements.


-
Component's ItemClick event:
- -
Clicked item: @clickedItem
+
Component's style & class:
+ +


-
Item's Click event:
- -
Click count: @clickCounter
+
Item's style & class:
+ +
+

+
+
Styles & Classes:
+ + +
- +
Use BitButtonGroup in right-to-left (RTL).

diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.cs index 15b29a29c7..32b455a4da 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.cs @@ -38,9 +38,9 @@ public partial class _BitButtonGroupItemDemo private List toggledItems = [ - new() { OnText = "Back (2X)", OffText = "Back", OnIconName = BitIconName.RewindTwoX, OffIconName = BitIconName.Rewind }, + new() { OnText = "Back (2X)", OffText = "Back (1X)", OnIconName = BitIconName.RewindTwoX, OffIconName = BitIconName.Rewind }, new() { OnTitle = "Resume", OffTitle = "Play", OnIconName = BitIconName.PlayResume, OffIconName = BitIconName.Play }, - new() { OnText = "Forward (2X)", OffText = "Forward", OnIconName = BitIconName.FastForwardTwoX, OffIconName = BitIconName.FastForward, ReversedIcon = true } + new() { OnText = "Forward (2X)", OffText = "Forward (1X)", OnIconName = BitIconName.FastForwardTwoX, OffIconName = BitIconName.FastForward, ReversedIcon = true } ]; private List eventsItems = diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cs index e41be97a4f..39dbd06ce2 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cs @@ -34,6 +34,127 @@ public partial class _BitButtonGroupItemDemo ];"; private readonly string example3RazorCode = @" + + +"; + private readonly string example3CsharpCode = @" +private List iconItems = +[ + new() { Text = ""Add"", IconName = BitIconName.Add }, + new() { Text = ""Edit"", IconName = BitIconName.Edit }, + new() { Text = ""Delete"", IconName = BitIconName.Delete } +];"; + + private readonly string example4RazorCode = @" + + + + + + +"; + private readonly string example4CsharpCode = @" +private List iconItems = +[ + new() { Text = ""Add"", IconName = BitIconName.Add }, + new() { Text = ""Edit"", IconName = BitIconName.Edit }, + new() { Text = ""Delete"", IconName = BitIconName.Delete } +]; + +private List onlyIconItems = +[ + new() { Text = ""Add"", IconName = BitIconName.Add }, + new() { IconName = BitIconName.Edit }, + new() { Text = ""Delete"", IconName = BitIconName.Delete } +];"; + + private readonly string example5RazorCode = @" + + +"; + private readonly string example5CsharpCode = @" +private List reversedIconItems = +[ + new() { Text = ""Add"", IconName = BitIconName.Add, ReversedIcon = true }, + new() { Text = ""Edit"", IconName = BitIconName.Edit, ReversedIcon = true }, + new() { Text = ""Delete"", IconName = BitIconName.Delete, ReversedIcon = true } +];"; + + private readonly string example6RazorCode = @" + + +"; + private readonly string example6CsharpCode = @" +private List toggledItems = +[ + new() { OnText = ""Back (2X)"", OffText = ""Back (1X)"", OnIconName = BitIconName.RewindTwoX, OffIconName = BitIconName.Rewind }, + new() { OnTitle = ""Resume"", OffTitle = ""Play"", OnIconName = BitIconName.PlayResume, OffIconName = BitIconName.Play }, + new() { OnText = ""Forward (2X)"", OffText = ""Forward (1X)"", OnIconName = BitIconName.FastForwardTwoX, OffIconName = BitIconName.FastForward, ReversedIcon = true } +];"; + + private readonly string example7RazorCode = @" + + +"; + private readonly string example7CsharpCode = @" +private List basicItems = +[ + new() { Text = ""Add"" }, new() { Text = ""Edit"" }, new() { Text = ""Delete"" } +];"; + + private readonly string example8RazorCode = @" + clickedItem = item.Text"" /> +
Clicked item: @clickedItem
+ + +
Click count: @clickCounter
"; + private readonly string example8CsharpCode = @" +private int clickCounter; +private string? clickedItem; + +private List eventsItems = +[ + new() { Text = ""Increase"", IconName = BitIconName.Add }, + new() { Text = ""Reset"", IconName = BitIconName.Reset }, + new() { Text = ""Decrease"", IconName = BitIconName.Remove } +]; + +protected override void OnInitialized() +{ + eventsItems[0].OnClick = _ => { clickCounter++; StateHasChanged(); }; + eventsItems[1].OnClick = _ => { clickCounter = 0; StateHasChanged(); }; + eventsItems[2].OnClick = _ => { clickCounter--; StateHasChanged(); }; +}"; + + private readonly string example9RazorCode = @" + + + + + + + + + + +"; + private readonly string example9CsharpCode = @" +private List basicItems = +[ + new() { Text = ""Add"" }, new() { Text = ""Edit"" }, new() { Text = ""Delete"" } +];"; + + private readonly string example10RazorCode = @" + + +"; + private readonly string example10CsharpCode = @" +private List basicItems = +[ + new() { Text = ""Add"" }, new() { Text = ""Edit"" }, new() { Text = ""Delete"" } +];"; + + private readonly string example11RazorCode = @" @@ -104,100 +225,13 @@ public partial class _BitButtonGroupItemDemo "; - private readonly string example3CsharpCode = @" + private readonly string example11CsharpCode = @" private List basicItems = [ new() { Text = ""Add"" }, new() { Text = ""Edit"" }, new() { Text = ""Delete"" } ];"; - private readonly string example4RazorCode = @" - - -"; - private readonly string example4CsharpCode = @" -private List iconItems = -[ - new() { Text = ""Add"", IconName = BitIconName.Add }, - new() { Text = ""Edit"", IconName = BitIconName.Edit }, - new() { Text = ""Delete"", IconName = BitIconName.Delete } -];"; - - private readonly string example5RazorCode = @" - - - - - - -"; - private readonly string example5CsharpCode = @" -private List iconItems = -[ - new() { Text = ""Add"", IconName = BitIconName.Add }, - new() { Text = ""Edit"", IconName = BitIconName.Edit }, - new() { Text = ""Delete"", IconName = BitIconName.Delete } -]; - -private List onlyIconItems = -[ - new() { Text = ""Add"", IconName = BitIconName.Add }, - new() { IconName = BitIconName.Edit }, - new() { Text = ""Delete"", IconName = BitIconName.Delete } -];"; - - private readonly string example6RazorCode = @" - - -"; - private readonly string example6CsharpCode = @" -private List reversedIconItems = -[ - new() { Text = ""Add"", IconName = BitIconName.Add, ReversedIcon = true }, - new() { Text = ""Edit"", IconName = BitIconName.Edit, ReversedIcon = true }, - new() { Text = ""Delete"", IconName = BitIconName.Delete, ReversedIcon = true } -];"; - - private readonly string example7RazorCode = @" - - -"; - private readonly string example7CsharpCode = @" -private List toggledItems = -[ - new() { OnText = ""Back (2X)"", OffText = ""Back"", OnIconName = BitIconName.RewindTwoX, OffIconName = BitIconName.Rewind }, - new() { OnTitle = ""Resume"", OffTitle = ""Play"", OnIconName = BitIconName.PlayResume, OffIconName = BitIconName.Play }, - new() { OnText = ""Forward (2X)"", OffText = ""Forward"", OnIconName = BitIconName.FastForwardTwoX, OffIconName = BitIconName.FastForward, ReversedIcon = true } -];"; - - private readonly string example8RazorCode = @" - - -"; - private readonly string example8CsharpCode = @" -private List basicItems = -[ - new() { Text = ""Add"" }, new() { Text = ""Edit"" }, new() { Text = ""Delete"" } -];"; - - private readonly string example9RazorCode = @" - - - - - - - - - - -"; - private readonly string example9CsharpCode = @" -private List basicItems = -[ - new() { Text = ""Add"" }, new() { Text = ""Edit"" }, new() { Text = ""Delete"" } -];"; - - private readonly string example10RazorCode = @" + private readonly string example12RazorCode = @" -"; - private readonly string example10CsharpCode = @" + + + + +"; + private readonly string example12CsharpCode = @" private List basicItems = [ new() { Text = ""Add"" }, new() { Text = ""Edit"" }, new() { Text = ""Delete"" } @@ -249,35 +297,11 @@ public partial class _BitButtonGroupItemDemo } ];"; - private readonly string example11RazorCode = @" - clickedItem = item.Text"" /> -
Clicked item: @clickedItem
- - -
Click count: @clickCounter
"; - private readonly string example11CsharpCode = @" -private int clickCounter; -private string? clickedItem; - -private List eventsItems = -[ - new() { Text = ""Increase"", IconName = BitIconName.Add }, - new() { Text = ""Reset"", IconName = BitIconName.Reset }, - new() { Text = ""Decrease"", IconName = BitIconName.Remove } -]; - -protected override void OnInitialized() -{ - eventsItems[0].OnClick = _ => { clickCounter++; StateHasChanged(); }; - eventsItems[1].OnClick = _ => { clickCounter = 0; StateHasChanged(); }; - eventsItems[2].OnClick = _ => { clickCounter--; StateHasChanged(); }; -}"; - - private readonly string example12RazorCode = @" + private readonly string example13RazorCode = @" "; - private readonly string example12CsharpCode = @" + private readonly string example13CsharpCode = @" private List rtlItems = [ new() { Text = ""اضافه کردن"", IconName = BitIconName.Add }, diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor index 6828f69be3..df33bccf57 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor @@ -55,7 +55,287 @@
- + + +
Each item in the ButtonGroup can have an icon.
+

+
+
Fill (default)
+ + + + + +
+

+
+
Outline
+ + + + + +
+

+
+
Text
+ + + + + +
+
+
+ + + +
The IconOnly allows buttons to display only icons without any text, ideal for minimalistic designs or limited space.
+

+
+
Fill (default)
+ + + + + +
+

+
+
Outline
+ + + + + +
+

+
+
Text
+ + + + + +
+

+
Alternatively, each button can be set to IconOnly by simply leaving the text field empty.
+

+
+
Fill (default)
+ + + + + +
+

+
+
Outline
+ + + + + +
+

+
+
Text
+ + + + + +
+
+
+ + + +
Reverses the positions of the icon and the main content of the button.
+

+
+
Fill (default)
+ + + + + +
+

+
+
Outline
+ + + + + +
+

+
+
Text
+ + + + + +
+
+
+ + + +
The Toggle in BitButtonGroup allows you to control the active or inactive state of each button, providing clear visual feedback to users about which buttons are selected or currently in use.
+

+
+
Fill (default)
+ + + + + +
+

+
+
Outline
+ + + + + +
+

+
+
Text
+ + + + + +
+
+
+ + + +
By default the BitButtonGroup component is horizontal, but can be turned vertical by adding the Vertical property.
+

+
+
+
Fill (default)
+ + + +
+

+
+
Outline
+ + + +
+

+
+
Text
+ + + +
+
+
+
+ + + +
Managing button click events.
+

+
+
Component's ItemClick event:
+ + + + + +
Clicked item: @clickedOption
+
+

+
+
Item's Click event:
+ + + + + +
Click count: @clickCounter
+
+
+
+ + + +
Different sizes for buttons to meet design needs, ensuring flexibility within your application.
+

+
+
Small
+ + + + + + + + + +
+

+
+
Medium
+ + + + + + + + + +
+

+
+
Large
+ + + + + + + + + +
+
+
+ + + +
Setting the FullWidth makes the button group occupy 100% of its container's width.
+

+
+ + + + + + + + + +
+
+
+ + +
Offering a range of specialized colors, providing visual cues for specific states within your application.


@@ -284,242 +564,7 @@
- - -
Each item in the ButtonGroup can have an icon.
-

-
-
Fill (default)
- - - - - -
-

-
-
Outline
- - - - - -
-

-
-
Text
- - - - - -
-
-
- - - -
The IconOnly allows buttons to display only icons without any text, ideal for minimalistic designs or limited space.
-

-
-
Fill (default)
- - - - - -
-

-
-
Outline
- - - - - -
-

-
-
Text
- - - - - -
-

-
Alternatively, each button can be set to IconOnly by simply leaving the text field empty.
-

-
-
Fill (default)
- - - - - -
-

-
-
Outline
- - - - - -
-

-
-
Text
- - - - - -
-
-
- - - -
Reverses the positions of the icon and the main content of the button.
-

-
-
Fill (default)
- - - - - -
-

-
-
Outline
- - - - - -
-

-
-
Text
- - - - - -
-
-
- - - -
The Toggled in BitButtonGroup allows you to control the active or inactive state of each button, providing clear visual feedback to users about which buttons are selected or currently in use.
-

-
-
Fill (default)
- - - - - -
-

-
-
Outline
- - - - - -
-

-
-
Text
- - - - - -
-
-
- - - -
By default the BitButtonGroup component is horizontal, but can be turned vertical by adding the Vertical property.
-

-
-
-
Fill (default)
- - - -
-

-
-
Outline
- - - -
-

-
-
Text
- - - -
-
-
-
- - - -
Different sizes for buttons to meet design needs, ensuring flexibility within your application.
-

-
-
Small
- - - - - - - - - -
-

-
-
Medium
- - - - - - - - - -
-

-
-
Large
- - - - - - - - - -
-
-
- - +
Empower customization by overriding default styles and classes, allowing tailored design modifications to suit specific UI requirements.


@@ -541,36 +586,25 @@ -
-
- - - -
Managing button click events.


-
Component's ItemClick event:
- - - - +
Styles & Classes:
+ + -
Clicked item: @clickedOption
-
-

-
-
Item's Click event:
- - - - + + + -
Click count: @clickCounter
- +
Use BitButtonGroup in right-to-left (RTL).

diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cs index 796c28abae..df2b7ad4b4 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cs @@ -41,6 +41,175 @@ public partial class _BitButtonGroupOptionDemo "; private readonly string example3RazorCode = @" + + + + + + + + + + + + + + + + +"; + + private readonly string example4RazorCode = @" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +"; + + private readonly string example5RazorCode = @" + + + + + + + + + + + + + + + + +"; + + private readonly string example6RazorCode = @" + + + + + + + + + + + + + + + + +"; + + private readonly string example7RazorCode = @" + + + + + + + + + + +"; + + private readonly string example8RazorCode = @" + clickedOption = item.Text"" TItem=""BitButtonGroupOption""> + + + + +
Clicked item: @clickedOption
+ + + { clickCounter++; StateHasChanged(); }"" /> + { clickCounter=0; StateHasChanged(); }"" /> + { clickCounter--; StateHasChanged(); }"" /> + +
Click count: @clickCounter
"; + private readonly string example8CsharpCode = @" +private int clickCounter; +private string? clickedOption;"; + + private readonly string example9RazorCode = @" + + + + + + + + + + + + + + + + + + + + + + + + + + + + +"; + + private readonly string example10RazorCode = @" + + + + + + + + +"; + + private readonly string example11RazorCode = @" @@ -214,147 +383,7 @@ public partial class _BitButtonGroupOptionDemo "; - private readonly string example4RazorCode = @" - - - - - - - - - - - - - - - - -"; - - private readonly string example5RazorCode = @" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"; - - private readonly string example6RazorCode = @" - - - - - - - - - - - - - - - - -"; - - private readonly string example7RazorCode = @" - - - - - - - - - - - - - - - - -"; - - private readonly string example8RazorCode = @" - - - - - - - - - - -"; - - private readonly string example9RazorCode = @" - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"; - - private readonly string example10RazorCode = @" + private readonly string example12RazorCode = @" @@ -392,27 +427,21 @@ public partial class _BitButtonGroupOptionDemo -"; - - private readonly string example11RazorCode = @" - clickedOption = item.Text"" TItem=""BitButtonGroupOption""> - - - -
Clicked item: @clickedOption
- - { clickCounter++; StateHasChanged(); }"" /> - { clickCounter=0; StateHasChanged(); }"" /> - { clickCounter--; StateHasChanged(); }"" /> + + -
Click count: @clickCounter
"; - private readonly string example11CsharpCode = @" -private int clickCounter; -private string? clickedOption;"; - private readonly string example12RazorCode = @" + + +"; + + private readonly string example13RazorCode = @" diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/AppShell/BitAppShellDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/AppShell/BitAppShellDemo.razor new file mode 100644 index 0000000000..13f7921925 --- /dev/null +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/AppShell/BitAppShellDemo.razor @@ -0,0 +1,25 @@ +@page "/components/appshell" + +@inherits AppComponentBase + + + + + + +
Since this component is a base layout container, it is not possible to show its capabilities in a demo sample here.
+
+ You can always check our Boilerplate project template samples + (AdminPanel & + Todo) + to see the BitAppShell in action. +
+
+
+
\ No newline at end of file diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/AppShell/BitAppShellDemo.razor.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/AppShell/BitAppShellDemo.razor.cs new file mode 100644 index 0000000000..570afca29a --- /dev/null +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/AppShell/BitAppShellDemo.razor.cs @@ -0,0 +1,133 @@ +namespace Bit.BlazorUI.Demo.Client.Core.Pages.Components.Extras.AppShell; + +public partial class BitAppShellDemo +{ + private readonly List componentParameters = + [ + new() + { + Name = "CascadingValues", + Type = "IEnumerable?", + DefaultValue = "null", + Description = "The cascading values to be provided for the children of the layout.", + LinkType = LinkType.Link, + Href = "#cascading-value" + }, + new() + { + Name = "ChildContent", + Type = "RenderFragment?", + DefaultValue = "null", + Description = "The content of the layout.", + }, + new() + { + Name = "Classes", + Type = "BitAppShellClassStyles?", + DefaultValue = "null", + Description = "Custom CSS classes for different parts of the layout.", + LinkType = LinkType.Link, + Href = "#class-styles" + }, + new() + { + Name = "Styles", + Type = "BitAppShellClassStyles?", + DefaultValue = "null", + Description = "Custom CSS styles for different parts of the layout.", + LinkType = LinkType.Link, + Href = "#class-styles" + }, + ]; + + private readonly List componentSubClasses = + [new() + { + Id = "cascading-value", + Title = "BitCascadingValue", + Description = "The cascading value to be provided using the BitCascadingValueProvider component.", + Parameters = + [ + new() + { + Name = "Name", + Type = "string?", + DefaultValue = "null", + Description = "The optional name of the cascading value.", + }, + new() + { + Name = "Value", + Type = "object?", + DefaultValue = "null", + Description = "The value to be provided.", + }, + new() + { + Name = "IsFixed", + Type = "bool", + DefaultValue = "null", + Description = "If true, indicates that Value will not change.", + } + ] + }, + new() + { + Id = "class-styles", + Title = "BitAppShellClassStyles", + Parameters = + [ + new() + { + Name = "Root", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the root of the BitAppShell.", + }, + new() + { + Name = "Top", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the top area of the BitAppShell.", + }, + new() + { + Name = "Center", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the top center of the BitAppShell.", + }, + new() + { + Name = "Left", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the top left of the BitAppShell.", + }, + new() + { + Name = "Main", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the main area of the BitAppShell.", + }, + new() + { + Name = "Right", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the right area of the BitAppShell.", + }, + new() + { + Name = "Bottom", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the bottom area of the BitAppShell.", + }, + ] + } + ]; + +} diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/AppShell/BitAppShellDemo.razor.scss b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/AppShell/BitAppShellDemo.razor.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/NavPanel/BitNavPanelDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/NavPanel/BitNavPanelDemo.razor new file mode 100644 index 0000000000..2a002c5dc2 --- /dev/null +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/NavPanel/BitNavPanelDemo.razor @@ -0,0 +1,31 @@ +@page "/components/navpanel" + +@inherits AppComponentBase + + + + + + +
+ +
+ +
+
+ + + +
+ +
+ +
+
+
\ No newline at end of file diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/NavPanel/BitNavPanelDemo.razor.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/NavPanel/BitNavPanelDemo.razor.cs new file mode 100644 index 0000000000..861c32f955 --- /dev/null +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/NavPanel/BitNavPanelDemo.razor.cs @@ -0,0 +1,401 @@ + +namespace Bit.BlazorUI.Demo.Client.Core.Pages.Components.Extras.NavPanel; + +public partial class BitNavPanelDemo +{ + private readonly List componentParameters = + [ + new() + { + Name = "Classes", + Type = "BitNavPanelClassStyles?", + DefaultValue = "null", + Description = "Custom CSS classes for different parts of the nav panel.", + Href = "#class-styles", + LinkType = LinkType.Link, + }, + new() + { + Name = "EmptyListTemplate", + Type = "RenderFragment?", + DefaultValue = "null", + Description = "The custom template for when the search result is empty.", + }, + new() + { + Name = "EmptyListMessage", + Type = "string?", + DefaultValue = "null", + Description = "The custom message for when the search result is empty.", + }, + new() + { + Name = "Footer", + Type = "RenderFragment?", + DefaultValue = "null", + Description = "The custom template to render as the footer of the nav panel.", + }, + new() + { + Name = "Header", + Type = "RenderFragment?", + DefaultValue = "null", + Description = "The custom template to render as the header of the nav panel.", + }, + new() + { + Name = "IconUrl", + Type = "string?", + DefaultValue = "null", + Description = "The icon url to show in the header of the nav panel.", + }, + new() + { + Name = "IsOpen", + Type = "bool", + DefaultValue = "false", + Description = "Determines if the nav panel is open in small screens.", + }, + new() + { + Name = "IsToggled", + Type = "bool", + DefaultValue = "false", + Description = "Determines if the nav panel is in the toggled state.", + }, + new() + { + Name = "Items", + Type = "IList", + DefaultValue = "[]", + Description = "A collection of items to display in the nav panel.", + }, + new() + { + Name = "NavClasses", + Type = "BitNavClassStyles?", + DefaultValue = "null", + Description = "Custom CSS classes for different parts of the nav component of the nav panel.", + }, + new() + { + Name = "NavStyles", + Type = "BitNavClassStyles?", + DefaultValue = "null", + Description = "Custom CSS styles for different parts of the nav component of the nav panel.", + }, + new() + { + Name = "NoPad", + Type = "bool", + DefaultValue = "false", + Description = "Disables the padded mode of the nav panel.", + }, + new() + { + Name = "NoToggle", + Type = "bool", + DefaultValue = "false", + Description = "Disables the toggle feature of the nav panel.", + }, + new() + { + Name = "OnItemClick", + Type = "EventCallback", + DefaultValue = "", + Description = "Event fired up when an item is clicked.", + }, + new() + { + Name = "SearchBoxClasses", + Type = "BitSearchBoxClassStyles?", + DefaultValue = "null", + Description = "Custom CSS classes for different parts of the search box of the nav panel.", + }, + new() + { + Name = "SearchBoxPlaceholder", + Type = "string?", + DefaultValue = "null", + Description = "The placeholder of the input element of the search box of the nav panel.", + }, + new() + { + Name = "SearchBoxStyles", + Type = "BitSearchBoxClassStyles?", + DefaultValue = "null", + Description = "Custom CSS styles for different parts of the search box of the nav panel.", + }, + new() + { + Name = "Styles", + Type = "BitNavPanelClassStyles?", + DefaultValue = "null", + Description = "Custom CSS styles for different parts of the nav panel.", + Href = "#class-styles", + LinkType = LinkType.Link, + }, + new() + { + Name = "Top", + Type = "int", + DefaultValue = "0", + Description = "The top CSS property value of the root element of the nav panel in px.", + }, + ]; + + private readonly List componentSubClasses = + [ + new() + { + Id = "class-styles", + Title = "BitNavPanelClassStyles", + Parameters= + [ + new() + { + Name = "Overlay", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the overlay of the BitNavPanel.", + }, + new() + { + Name = "Root", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the root element of the BitNavPanel.", + }, + new() + { + Name = "Container", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the container of the BitNavPanel.", + }, + new() + { + Name = "Header", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the header container of the BitNavPanel.", + }, + new() + { + Name = "HeaderIcon", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the header icon of the BitNavPanel.", + }, + new() + { + Name = "ToggleButton", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the toggle button of the BitNavPanel.", + }, + new() + { + Name = "SearchBox", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the search box of the BitNavPanel.", + }, + new() + { + Name = "ToggleSearchButton", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the toggle search button of the BitNavPanel.", + }, + new() + { + Name = "EmptyListMessage", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the empty list message of the BitNavPanel.", + }, + new() + { + Name = "Nav", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the nav component of the BitNavPanel.", + }, + ] + } + ]; + + + + private bool basicIsOpen; + private bool rtlIsOpen; + private List basicNavItems = + [ + new() + { + Text = "Home", + IconName = BitIconName.Home, + Url = "HomePage", + }, + new() + { + Text = "AdminPanel", + IconName = BitIconName.Admin, + ChildItems = + [ + new() { + Text = "Dashboard", + IconName = BitIconName.BarChartVerticalFill, + Url = "DashboardPage", + }, + new() { + Text = "Categories", + IconName = BitIconName.BuildQueue, + Url = "CategoriesPage", + }, + new() { + Text = "Products", + IconName = BitIconName.Product, + Url = "ProductsPage", + } + ] + }, + new() + { + Text = "Todo", + IconName = BitIconName.ToDoLogoOutline, + Url = "TodoPage", + }, + new() + { + Text = "Settings", + IconName = BitIconName.Equalizer, + Url = "SettingsPage" + }, + new() + { + Text = "Terms", + IconName = BitIconName.EntityExtraction, + Url = "TermsPage", + } + ]; + + + + private readonly string example1RazorCode = @" + + +"; + private readonly string example1CsharpCode = @" +private bool basicIsOpen; + +private List basicNavItems = +[ + new() + { + Text = ""Home"", + IconName = BitIconName.Home, + Url = ""HomePage"", + }, + new() + { + Text = ""AdminPanel"", + IconName = BitIconName.Admin, + ChildItems = + [ + new() { + Text = ""Dashboard"", + IconName = BitIconName.BarChartVerticalFill, + Url = ""DashboardPage"", + }, + new() { + Text = ""Categories"", + IconName = BitIconName.BuildQueue, + Url = ""CategoriesPage"", + }, + new() { + Text = ""Products"", + IconName = BitIconName.Product, + Url = ""ProductsPage"", + } + ] + }, + new() + { + Text = ""Todo"", + IconName = BitIconName.ToDoLogoOutline, + Url = ""TodoPage"", + }, + new() + { + Text = ""Settings"", + IconName = BitIconName.Equalizer, + Url = ""SettingsPage"" + }, + new() + { + Text = ""Terms"", + IconName = BitIconName.EntityExtraction, + Url = ""TermsPage"", + } +];"; + + private readonly string example2RazorCode = @" + + +"; + private readonly string example2CsharpCode = @" +private bool rtlIsOpen; + +private List basicNavItems = +[ + new() + { + Text = ""Home"", + IconName = BitIconName.Home, + Url = ""HomePage"", + }, + new() + { + Text = ""AdminPanel"", + IconName = BitIconName.Admin, + ChildItems = + [ + new() { + Text = ""Dashboard"", + IconName = BitIconName.BarChartVerticalFill, + Url = ""DashboardPage"", + }, + new() { + Text = ""Categories"", + IconName = BitIconName.BuildQueue, + Url = ""CategoriesPage"", + }, + new() { + Text = ""Products"", + IconName = BitIconName.Product, + Url = ""ProductsPage"", + } + ] + }, + new() + { + Text = ""Todo"", + IconName = BitIconName.ToDoLogoOutline, + Url = ""TodoPage"", + }, + new() + { + Text = ""Settings"", + IconName = BitIconName.Equalizer, + Url = ""SettingsPage"" + }, + new() + { + Text = ""Terms"", + IconName = BitIconName.EntityExtraction, + Url = ""TermsPage"", + } +];"; +} diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/NavPanel/BitNavPanelDemo.razor.scss b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/NavPanel/BitNavPanelDemo.razor.scss new file mode 100644 index 0000000000..48203604cf --- /dev/null +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/NavPanel/BitNavPanelDemo.razor.scss @@ -0,0 +1,10 @@ +@import "../../../../Styles/abstracts/_media-queries.scss"; + +.open-btn { + display: none; + justify-content: center; + + @include lt-lg { + display: flex; + } +} diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Layouts/Layout/BitLayoutDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Layouts/Layout/BitLayoutDemo.razor index 87c7bec1ef..5c6946ff4a 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Layouts/Layout/BitLayoutDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Layouts/Layout/BitLayoutDemo.razor @@ -1,7 +1,7 @@ @page "/components/layout"
- + - +
- +
Header
- - - + + +
Main
@@ -55,36 +55,11 @@
Header
- NavMenu -
Main
-
Footer
-
-
-
-
- - - -
- - -
-
-
- -
Header
- NavMenu + NavPanel
Main
Footer
diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Layouts/Layout/BitLayoutDemo.razor.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Layouts/Layout/BitLayoutDemo.razor.cs index 9762cf4716..1758c31bc0 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Layouts/Layout/BitLayoutDemo.razor.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Layouts/Layout/BitLayoutDemo.razor.cs @@ -14,20 +14,6 @@ public partial class BitLayoutDemo Href = "#class-styles" }, new() - { - Name = "FixedHeader", - Type = "bool", - DefaultValue = "false", - Description = "Enables fixed positioning of the header at the top of the viewport.", - }, - new() - { - Name = "FixedFooter", - Type = "bool", - DefaultValue = "false", - Description = "Enables fixed positioning of the footer at the bottom of the viewport.", - }, - new() { Name = "Footer", Type = "RenderFragment?", @@ -35,13 +21,6 @@ public partial class BitLayoutDemo Description = "The content of the footer section.", }, new() - { - Name = "FooterHeight", - Type = "int", - DefaultValue = "0", - Description = "The height of the footer to calculate heights and paddings.", - }, - new() { Name = "Header", Type = "RenderFragment?", @@ -50,17 +29,10 @@ public partial class BitLayoutDemo }, new() { - Name = "HeaderHeight", - Type = "int", - DefaultValue = "0", - Description = "The height of the header to calculate heights and paddings.", - }, - new() - { - Name = "HideNavMenu", + Name = "HideNavPanel", Type = "bool", DefaultValue = "false", - Description = "Hides NavMenu content when true.", + Description = "Hides NavPanel content when true.", }, new() { @@ -71,17 +43,17 @@ public partial class BitLayoutDemo }, new() { - Name = "NavMenu", + Name = "NavPanel", Type = "RenderFragment?", DefaultValue = "null", - Description = "The content of the nav-menu section.", + Description = "The content of the nav panel section.", }, new() { - Name = "StatusBarHeight", + Name = "NavPanelWidth", Type = "int", DefaultValue = "0", - Description = "The height of the status bar on mobile devices to calculate heights and paddings.", + Description = "The width of the nav panel section in px.", }, new() { @@ -91,7 +63,21 @@ public partial class BitLayoutDemo Description = "Custom CSS styles for different parts of the BitLayout.", LinkType = LinkType.Link, Href = "#class-styles" - } + }, + new() + { + Name = "StickyFooter", + Type = "bool", + DefaultValue = "false", + Description = "Enables sticky positioning of the footer at the bottom of the viewport.", + }, + new() + { + Name = "StickyHeader", + Type = "bool", + DefaultValue = "false", + Description = "Enables sticky positioning of the header at the top of the viewport.", + }, ]; private readonly List componentSubClasses = @@ -125,7 +111,7 @@ public partial class BitLayoutDemo }, new() { - Name = "NavMenu", + Name = "NavPanel", Type = "string?", DefaultValue = "null", Description = "Custom CSS classes/styles for the nav-menu section of the BitLayout." @@ -150,10 +136,8 @@ public partial class BitLayoutDemo - private bool hideNavMenu; + private bool HideNavPanel; - private int headerHeight = 60; - private int footerHeight = 60; private readonly string example1RazorCode = @" @@ -217,15 +201,15 @@ public partial class BitLayoutDemo - + - +
Header
- -
NavMenu
-
+ +
NavPanel
+
Main
@@ -234,7 +218,7 @@ public partial class BitLayoutDemo
"; private readonly string example2CsharpCode = @" -private bool hideNavMenu;"; +private bool HideNavPanel;"; private readonly string example3RazorCode = @"