Initialize Blazor SSR project structure
This commit is contained in:
59
.gitignore
vendored
Normal file
59
.gitignore
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
## .NET
|
||||
bin/
|
||||
obj/
|
||||
*.user
|
||||
*.suo
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
.vs/
|
||||
.vscode/
|
||||
|
||||
## Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
## Visual Studio cache/options directory
|
||||
.vs/
|
||||
.vscode/
|
||||
|
||||
## JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
## User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
## ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
## Publish profiles
|
||||
*.pubxml
|
||||
*.azurePubxml
|
||||
|
||||
## NuGet Packages
|
||||
*.nupkg
|
||||
*.snupkg
|
||||
**/packages/*
|
||||
|
||||
## Node.js (keeping for now, will remove after React cleanup)
|
||||
node_modules/
|
||||
package-lock.json
|
||||
|
||||
## OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
766
migration.md
Normal file
766
migration.md
Normal file
@@ -0,0 +1,766 @@
|
||||
# Blazor SSR Migration Plan
|
||||
|
||||
## Project Overview
|
||||
Migrating a React/TypeScript portfolio website to a **minimal, dependency-free** .NET Blazor application with static server-side rendering.
|
||||
|
||||
**Current Stack:**
|
||||
- React 18.2 + TypeScript
|
||||
- Vite build tool
|
||||
- Tailwind CSS (to be replaced with vanilla CSS)
|
||||
- React Router DOM
|
||||
- Headless UI components (Dialog/Tabs - to be replaced with vanilla HTML/CSS/JS)
|
||||
- React Icons (to be replaced with SVG icons)
|
||||
- Azure Static Web Apps hosting
|
||||
|
||||
**Target Stack:**
|
||||
- .NET 10 Blazor with Static SSR (no WebSockets/SignalR)
|
||||
- C# Razor components (server-rendered only)
|
||||
- **Vanilla CSS only** (no frameworks, no preprocessors)
|
||||
- Blazor Router (built-in)
|
||||
- **No external component libraries**
|
||||
- **No icon dependencies** (inline SVG)
|
||||
- Azure App Service or Azure Container Apps hosting
|
||||
|
||||
**Migration Philosophy:**
|
||||
- Zero external dependencies beyond .NET runtime
|
||||
- Simple, maintainable vanilla CSS
|
||||
- Static server-side rendering (no interactivity circuits)
|
||||
- Modern CSS features (Grid, Flexbox, CSS Variables, Container Queries)
|
||||
- Native HTML elements with custom styling
|
||||
- **Zero JavaScript** - pure CSS solutions for all interactivity (checkbox hack, :target pseudo-class)
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Project Setup
|
||||
|
||||
### 1.1 .NET Project Initialization
|
||||
- [ ] Install .NET 10 SDK
|
||||
- [ ] Create new Blazor Web App project with SSR only: `dotnet new blazor -o src/BlazorApp -int None`
|
||||
- Note: `-int None` disables interactivity (no SignalR/WebSockets)
|
||||
- [ ] Verify project builds: `dotnet build`
|
||||
- [ ] Review generated files: `Program.cs`, `App.razor`, `Components/_Imports.razor`, `appsettings.json`
|
||||
- [ ] Confirm `Program.cs` does NOT include `AddInteractiveServerComponents()` or SignalR setup
|
||||
|
||||
### 1.2 Solution Structure
|
||||
- [ ] Create solution file: `dotnet new sln -n my-portfolio`
|
||||
- [ ] Add project to solution: `dotnet sln add src/BlazorApp/BlazorApp.csproj`
|
||||
- [ ] Configure project properties (nullable, implicit usings)
|
||||
- [ ] Ensure render modes are set to static SSR only
|
||||
|
||||
### 1.3 Git Configuration
|
||||
- [ ] Update `.gitignore` for .NET (bin/, obj/, .vs/)
|
||||
- [ ] Archive React project (move to `archive/react-version/` or create `pre-blazor-migration` tag)
|
||||
- [ ] Commit initial Blazor project structure
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: CSS Architecture & Design System
|
||||
|
||||
### 2.1 CSS Variables Setup
|
||||
- [ ] Create `wwwroot/css/variables.css` with design tokens:
|
||||
- Colors (black: #000, white: #fff, gray shades)
|
||||
- Spacing scale (0.25rem, 0.5rem, 1rem, 1.5rem, 2rem, etc.)
|
||||
- Typography (font-family: monospace, font-sizes, line-heights)
|
||||
- Breakpoints (mobile-first: 640px, 768px, 1024px, 1280px)
|
||||
- Z-index scale
|
||||
- Border radius values
|
||||
- Transition durations
|
||||
|
||||
### 2.2 Base Styles
|
||||
- [ ] Create `wwwroot/css/reset.css` with modern CSS reset
|
||||
- [ ] Create `wwwroot/css/base.css`:
|
||||
- Body styles (background: black, color: slate-50, font: monospace)
|
||||
- Typography defaults
|
||||
- Link styles
|
||||
- Focus styles for accessibility
|
||||
- Custom scrollbar styles
|
||||
- Selection styles
|
||||
|
||||
### 2.3 Layout Utilities
|
||||
- [ ] Create `wwwroot/css/layout.css`:
|
||||
- Container classes (max-width, centering)
|
||||
- Flexbox utilities (flex, flex-col, items-center, justify-between, gap, etc.)
|
||||
- Grid utilities (grid, grid-cols)
|
||||
- Spacing utilities (padding, margin classes)
|
||||
- Responsive utilities
|
||||
|
||||
### 2.4 Component Styles
|
||||
- [ ] Create `wwwroot/css/components.css`:
|
||||
- Button styles (primary, secondary, hover, focus, disabled states)
|
||||
- Input/textarea styles
|
||||
- Card styles
|
||||
- Navigation styles
|
||||
- Footer styles
|
||||
- Link styles
|
||||
- [ ] Create `wwwroot/css/animations.css`:
|
||||
- Fade-in animation
|
||||
- Hover transitions
|
||||
- Loading spinner animation
|
||||
|
||||
### 2.5 Compile CSS
|
||||
- [ ] Create `wwwroot/css/app.css` that imports all CSS files
|
||||
- [ ] Reference in `index.html`: `<link href="css/app.css" rel="stylesheet" />`
|
||||
- [ ] Test CSS loads correctly
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: SVG Icon System
|
||||
|
||||
### 3.1 Extract Icons
|
||||
- [ ] Identify all react-icons used:
|
||||
- FaBars (hamburger menu)
|
||||
- FaXmark (close X)
|
||||
- FaGithub
|
||||
- FaLinkedin
|
||||
- FaEnvelope
|
||||
- FaDatabase
|
||||
- FaDocker
|
||||
- FaReact
|
||||
- SiCsharp
|
||||
- SiMicrosoftazure
|
||||
- SiBlazor
|
||||
- [ ] Download SVG paths from icon sources (FontAwesome, Simple Icons)
|
||||
- [ ] Create reusable Icon component: `Components/Icon.razor`
|
||||
|
||||
### 3.2 Icon Component
|
||||
- [ ] Implement `Icon.razor` with parameters:
|
||||
- `Name` (string): icon identifier
|
||||
- `Size` (int, default 24): icon size in pixels
|
||||
- `CssClass` (string): additional CSS classes
|
||||
- [ ] Store SVG paths in C# dictionary or switch statement
|
||||
- [ ] Test all icons render correctly
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Core Application Structure
|
||||
|
||||
### 4.1 Routing Setup
|
||||
- [ ] Configure routes in `App.razor`:
|
||||
- `/` → Home page
|
||||
- `/work` → Work page
|
||||
- `/about` → About page
|
||||
- `NotFound` → 404/Error page
|
||||
- [ ] Test routing and navigation
|
||||
|
||||
### 4.2 Layout Component
|
||||
- [ ] Create `Shared/MainLayout.razor`
|
||||
- [ ] Implement structure:
|
||||
- Header with NavBar
|
||||
- Main content area with `@Body`
|
||||
- Footer
|
||||
- [ ] Apply CSS classes (container, flex layout, min-height)
|
||||
- [ ] Add fade-in animation class
|
||||
- [ ] Test layout renders correctly
|
||||
|
||||
### 4.3 Navigation Component
|
||||
- [ ] Create `Shared/NavBar.razor`
|
||||
- [ ] Implement desktop navigation:
|
||||
- Logo image
|
||||
- Navigation links (Home, Work, About)
|
||||
- [ ] Implement mobile navigation:
|
||||
- Hamburger button (toggle mobile menu)
|
||||
- Mobile menu overlay with links
|
||||
- Close button
|
||||
- Social icons in mobile menu
|
||||
- [ ] Use Blazor's built-in `NavLink` component with custom styling
|
||||
- [ ] Implement mobile menu state with C# boolean property
|
||||
- [ ] Style with pure CSS (no Headless UI)
|
||||
|
||||
### 4.4 Footer Component
|
||||
- [ ] Create `Shared/Footer.razor`
|
||||
- [ ] Port footer content
|
||||
- [ ] Apply styling
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Page Components
|
||||
|
||||
### 5.1 Home Page
|
||||
- [ ] Create `Pages/Home.razor` with `@page "/"`
|
||||
- [ ] Port content from `HomePage.tsx`
|
||||
- [ ] Reference child components (Title, Text, TechIcons)
|
||||
- [ ] Test rendering
|
||||
|
||||
### 5.2 Work Page
|
||||
- [ ] Create `Pages/Work.razor` with `@page "/work"`
|
||||
- [ ] Port content from `WorkPage.tsx`
|
||||
- [ ] Test rendering
|
||||
|
||||
### 5.3 About Page
|
||||
- [ ] Create `Pages/About.razor` with `@page "/about"`
|
||||
- [ ] Port content from `AboutPage.tsx`
|
||||
- [ ] Test rendering
|
||||
|
||||
### 5.4 Error/404 Page
|
||||
- [ ] Create `Pages/NotFound.razor` with `@page "/404"`
|
||||
- [ ] Port content from `ErrorPage.tsx`
|
||||
- [ ] Configure as NotFound in router
|
||||
- [ ] Test 404 handling
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Reusable UI Components
|
||||
|
||||
### 6.1 Typography Components (7)
|
||||
- [ ] `Components/Title.razor` - H1 heading
|
||||
- [ ] `Components/Subtitle.razor` - H2 heading
|
||||
- [ ] `Components/Text.razor` - Paragraph with margin
|
||||
- [ ] `Components/Label.razor` - Form label
|
||||
- [ ] `Components/List.razor` - UL wrapper
|
||||
- [ ] `Components/ListItem.razor` - LI element
|
||||
- [ ] `Components/AnchorLink.razor` - External link with styling
|
||||
|
||||
### 6.2 Form Components (3)
|
||||
- [ ] `Components/Button.razor` - Button with hover/focus states
|
||||
- [ ] `Components/TextInput.razor` - Input field with label
|
||||
- [ ] `Components/TextAreaInput.razor` - Textarea with label
|
||||
|
||||
### 6.3 Display Components (5)
|
||||
- [ ] `Components/TechIcons.razor` - Tech stack grid with icons
|
||||
- [ ] `Components/SocialIcons.razor` - Social media links with icons
|
||||
- [ ] `Components/WorkTimeline.razor` - Work experience timeline
|
||||
- [ ] `Components/Loading.razor` - Loading state wrapper
|
||||
- [ ] `Components/LoadingSpinner.razor` - Spinner animation
|
||||
|
||||
### 6.4 Feature Components (2)
|
||||
- [ ] `Components/ContactMe.razor` - Contact form
|
||||
- [ ] `Components/AboutTabs.razor` - Tab interface (vanilla CSS/JS)
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: Interactive Components (Pure CSS - No JavaScript)
|
||||
|
||||
### 7.1 Mobile Menu (CSS Checkbox Hack)
|
||||
- [ ] Implement in `NavBar.razor`:
|
||||
- Add hidden checkbox: `<input type="checkbox" id="mobile-menu-toggle" class="menu-toggle" />`
|
||||
- Add label for hamburger: `<label for="mobile-menu-toggle">☰</label>`
|
||||
- Add label for close button inside menu: `<label for="mobile-menu-toggle">✕</label>`
|
||||
- Render menu panel as sibling to checkbox
|
||||
- [ ] Style with CSS:
|
||||
- Hide checkbox: `.menu-toggle { display: none; }`
|
||||
- Show/hide menu based on checkbox state: `.menu-toggle:checked ~ .mobile-menu { ... }`
|
||||
- Show/hide overlay: `.menu-toggle:checked ~ .overlay { ... }`
|
||||
- Slide-in animation using `transform: translateX()`
|
||||
- Transparent overlay with backdrop-filter blur
|
||||
- Z-index layering for proper stacking
|
||||
- [ ] Test keyboard navigation (checkbox is focusable)
|
||||
|
||||
### 7.2 Tabs Component (CSS :target Pseudo-Class or Radio Buttons)
|
||||
- [ ] **Option A - Radio Button Approach (Recommended):**
|
||||
- Create `AboutTabs.razor`:
|
||||
- Hidden radio inputs: `<input type="radio" name="tabs" id="tab1" checked />`
|
||||
- Label buttons: `<label for="tab1">Tab 1</label>`
|
||||
- Tab panels as siblings to inputs
|
||||
- Style with CSS:
|
||||
- Hide radio buttons: `input[type="radio"] { display: none; }`
|
||||
- Active tab styling: `#tab1:checked ~ .tabs-labels label[for="tab1"] { ... }`
|
||||
- Show panel: `#tab1:checked ~ .tab-panels .panel1 { display: block; }`
|
||||
- Hide other panels by default
|
||||
- [ ] **Option B - :target Pseudo-Class:**
|
||||
- Use anchor links: `<a href="#tab1">Tab 1</a>`
|
||||
- Panel IDs: `<div id="tab1" class="tab-panel">...</div>`
|
||||
- Style: `.tab-panel:target { display: block; }`
|
||||
- Note: Changes URL hash
|
||||
- [ ] Choose approach and implement
|
||||
- [ ] Add smooth transitions with CSS
|
||||
|
||||
### 7.3 Form Handling (Traditional POST)
|
||||
- [ ] Implement form submission in `ContactMe.razor`
|
||||
- [ ] Use standard HTML `<form>` with POST action
|
||||
- [ ] Server-side endpoint to handle form submission
|
||||
- [ ] Redirect after post pattern (PRG)
|
||||
- [ ] Add HTML5 validation attributes
|
||||
- [ ] Style validation states with CSS (`:invalid`, `:valid`)
|
||||
|
||||
---
|
||||
|
||||
## Phase 8: Tailwind CSS to Vanilla CSS Conversion
|
||||
|
||||
### 8.1 Analyze Tailwind Usage
|
||||
- [ ] Document all Tailwind classes used in current app:
|
||||
- Layout: `flex`, `flex-col`, `items-center`, `justify-between`, `max-w-7xl`, etc.
|
||||
- Spacing: `px-6`, `py-8`, `mt-4`, `mb-6`, `space-x-6`, etc.
|
||||
- Typography: `text-sm`, `text-xl`, `font-semibold`, `font-mono`, etc.
|
||||
- Colors: `bg-black`, `text-white`, `text-gray-200`, `ring-gray-300`, etc.
|
||||
- Responsive: `lg:flex`, `md:order-2`, `sm:max-w-sm`, etc.
|
||||
- Effects: `hover:bg-gray-800`, `focus-visible:outline`, etc.
|
||||
|
||||
### 8.2 Create CSS Equivalents
|
||||
- [ ] Create utility classes in `layout.css`:
|
||||
```css
|
||||
.flex { display: flex; }
|
||||
.flex-col { flex-direction: column; }
|
||||
.items-center { align-items: center; }
|
||||
.justify-between { justify-content: space-between; }
|
||||
.max-w-7xl { max-width: 80rem; margin: 0 auto; }
|
||||
.container { max-width: 1280px; margin: 0 auto; padding: 0 1.5rem; }
|
||||
```
|
||||
- [ ] Create spacing utilities:
|
||||
```css
|
||||
.px-6 { padding-left: 1.5rem; padding-right: 1.5rem; }
|
||||
.py-8 { padding-top: 2rem; padding-bottom: 2rem; }
|
||||
.mt-4 { margin-top: 1rem; }
|
||||
/* etc. */
|
||||
```
|
||||
- [ ] Create responsive utilities using media queries:
|
||||
```css
|
||||
@media (min-width: 1024px) {
|
||||
.lg\:flex { display: flex; }
|
||||
}
|
||||
```
|
||||
- [ ] Alternative: Use component-specific classes instead of utilities
|
||||
|
||||
### 8.3 Choose Approach
|
||||
- [ ] **Option A (Recommended):** Component-specific CSS classes
|
||||
- More maintainable for small projects
|
||||
- Better for this portfolio site (20 components)
|
||||
- Example: `.nav-bar {}`, `.nav-bar__logo {}`, `.nav-bar__menu {}`
|
||||
- [ ] **Option B:** Minimal utility classes
|
||||
- Create only the most-used utilities (flex, grid, spacing)
|
||||
- Combine with component classes
|
||||
- [ ] Document chosen approach in README
|
||||
|
||||
---
|
||||
|
||||
## Phase 9: SEO & Meta Tags
|
||||
|
||||
### 9.1 HTML Head Configuration
|
||||
- [ ] Update `wwwroot/index.html` with meta tags:
|
||||
- Charset, viewport
|
||||
- Description, author
|
||||
- Open Graph tags (og:title, og:description, og:image, og:url)
|
||||
- Favicon reference
|
||||
- [ ] Ensure all tags from React version are migrated
|
||||
- [ ] Test with social media preview tools
|
||||
|
||||
### 9.2 Analytics Integration
|
||||
- [ ] Add Google Analytics script to `index.html`
|
||||
- [ ] Add CookieYes consent script to `index.html`
|
||||
- [ ] Test analytics on navigation (use `NavigationManager.LocationChanged` if needed)
|
||||
- [ ] Verify GDPR compliance
|
||||
|
||||
---
|
||||
|
||||
## Phase 10: Build & Optimization
|
||||
|
||||
### 10.1 Build Configuration
|
||||
- [ ] Configure `.csproj` for optimizations:
|
||||
```xml
|
||||
<PropertyGroup>
|
||||
<PublishReadyToRun>true</PublishReadyToRun>
|
||||
<PublishReadyToRunShowWarnings>true</PublishReadyToRunShowWarnings>
|
||||
</PropertyGroup>
|
||||
```
|
||||
- [ ] Test production build: `dotnet publish -c Release`
|
||||
- [ ] Analyze output in `bin/Release/net10.0/publish/`
|
||||
- [ ] Verify CSS is minimal and unminified (easy to debug)
|
||||
- [ ] Verify NO JavaScript files present
|
||||
|
||||
### 10.2 CSS Optimization
|
||||
- [ ] Remove unused CSS
|
||||
- [ ] Combine CSS files if beneficial
|
||||
- [ ] Consider minification (optional - Azure handles this)
|
||||
- [ ] Test CSS loads and applies correctly
|
||||
- [ ] Verify CSS-only menu and tabs work in all browsers
|
||||
|
||||
### 10.3 Image Optimization
|
||||
- [ ] Verify `logo.webp` is optimized
|
||||
- [ ] Add width/height attributes to prevent layout shift
|
||||
- [ ] Test image loading
|
||||
|
||||
### 10.4 Zero JavaScript Verification
|
||||
- [ ] Confirm no `.js` files in `wwwroot/js/`
|
||||
- [ ] Confirm no `<script>` tags in layouts/pages
|
||||
- [ ] Test site functions without JavaScript enabled in browser
|
||||
|
||||
---
|
||||
|
||||
## Phase 11: Deployment Configuration
|
||||
|
||||
### 11.1 Azure App Service Configuration
|
||||
- [ ] Create Azure App Service (Linux or Windows)
|
||||
- [ ] Configure environment variables in Azure portal:
|
||||
- `ASPNETCORE_ENVIRONMENT=Production`
|
||||
- [ ] Enable HTTPS only
|
||||
- [ ] Configure health check endpoint
|
||||
- [ ] Set up Application Insights (optional)
|
||||
|
||||
### 11.2 GitHub Actions Workflow
|
||||
- [ ] Create/update `.github/workflows/azure-deploy.yml`:
|
||||
```yaml
|
||||
name: Deploy to Azure App Service
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '10.0.x'
|
||||
|
||||
- name: Build
|
||||
run: dotnet build src/BlazorApp/BlazorApp.csproj -c Release
|
||||
|
||||
- name: Publish
|
||||
run: dotnet publish src/BlazorApp/BlazorApp.csproj -c Release -o ${{env.DOTNET_ROOT}}/myapp
|
||||
|
||||
- name: Deploy to Azure Web App
|
||||
uses: azure/webapps-deploy@v2
|
||||
with:
|
||||
app-name: 'your-app-name'
|
||||
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
|
||||
package: ${{env.DOTNET_ROOT}}/myapp
|
||||
```
|
||||
- [ ] Set up Azure publish profile in GitHub secrets
|
||||
- [ ] Test workflow on branch
|
||||
|
||||
### 11.3 Local Development Setup
|
||||
- [ ] Document commands:
|
||||
- Run: `dotnet watch` (hot reload enabled)
|
||||
- Build: `dotnet build`
|
||||
- Publish: `dotnet publish -c Release`
|
||||
- [ ] Test hot reload functionality
|
||||
- [ ] Configure HTTPS for local dev (trust cert)
|
||||
- [ ] Verify no SignalR scripts loaded (check browser network tab)
|
||||
- [ ] Test CSS-only interactivity (menu, tabs) during development
|
||||
|
||||
---
|
||||
|
||||
## Phase 12: Testing & Quality Assurance
|
||||
|
||||
### 12.1 Visual Testing
|
||||
- [ ] Compare React site vs Blazor site side-by-side
|
||||
- [ ] Test all pages render identically
|
||||
- [ ] Test all components display correctly
|
||||
- [ ] Test responsive design:
|
||||
- Mobile (320px, 375px, 414px)
|
||||
- Tablet (768px, 1024px)
|
||||
- Desktop (1280px, 1920px)
|
||||
- [ ] Test cross-browser:
|
||||
- Chrome/Edge (Chromium)
|
||||
- Firefox
|
||||
- Safari (if available)
|
||||
|
||||
### 12.2 Functional Testing
|
||||
- [ ] Test navigation between pages (full page reloads)
|
||||
- [ ] Test mobile menu open/close (CSS checkbox)
|
||||
- [ ] Test tab switching in About page (CSS radio/target)
|
||||
- [ ] Test all external links
|
||||
- [ ] Test form submission with POST/redirect
|
||||
- [ ] Test 404 page navigation
|
||||
- [ ] Test with JavaScript disabled in browser
|
||||
- [ ] Verify no JavaScript errors (should be none)
|
||||
|
||||
### 12.3 Accessibility Testing
|
||||
- [ ] Test keyboard navigation (Tab, Enter, Space for checkboxes/radios)
|
||||
- [ ] Test screen reader compatibility (aria-labels, proper label associations)
|
||||
- [ ] Test focus indicators (especially on hidden checkbox/radio controls)
|
||||
- [ ] Test color contrast (black/white theme)
|
||||
- [ ] Verify checkbox and radio button labels are properly associated
|
||||
- [ ] Run Lighthouse accessibility audit
|
||||
|
||||
### 12.4 Performance Testing
|
||||
- [ ] Test server response times for page requests
|
||||
- [ ] Test First Contentful Paint (FCP)
|
||||
- [ ] Test Time to Interactive (TTI)
|
||||
- [ ] Test with throttled network (3G)
|
||||
- [ ] Verify no WebSocket connections in network tab
|
||||
- [ ] Verify no JavaScript downloads
|
||||
- [ ] Run Lighthouse performance audit
|
||||
- [ ] Target: FCP < 1s, TTI < 1.5s (server-rendered, zero JavaScript, instant interactive)
|
||||
|
||||
### 12.5 SEO Testing
|
||||
- [ ] Test meta tags with social media debuggers:
|
||||
- Facebook Sharing Debugger
|
||||
- Twitter Card Validator
|
||||
- LinkedIn Post Inspector
|
||||
- [ ] Test robots.txt accessibility
|
||||
- [ ] Test favicon in browser tabs
|
||||
- [ ] Run Lighthouse SEO audit
|
||||
|
||||
---
|
||||
|
||||
## Phase 13: Documentation & Cleanup
|
||||
|
||||
### 13.1 Update Documentation
|
||||
- [ ] Update README.md:
|
||||
```markdown
|
||||
# beaufindlay.com
|
||||
|
||||
My personal portfolio site built with .NET Blazor WebAssembly.
|
||||
|
||||
## Tech Stack
|
||||
- .NET 10 Blazor SSR (static server-side rendering)
|
||||
- Pure CSS only (zero JavaScript)
|
||||
- Hosted on Azure App Service
|
||||
|
||||
## Development
|
||||
- Run: `dotnet watch`
|
||||
- Build: `dotnet build`
|
||||
- Publish: `dotnet publish -c Release`
|
||||
|
||||
## Features
|
||||
- Zero external dependencies (no npm, no frameworks, no JavaScript)
|
||||
- Static server-side rendering (no WebSockets)
|
||||
- Pure CSS interactivity (checkbox hack for menu, radio buttons for tabs)
|
||||
- Mobile-first responsive design
|
||||
- Accessible and SEO-optimized
|
||||
- Works with JavaScript disabled
|
||||
```
|
||||
- [ ] Document CSS architecture in comments
|
||||
- [ ] Add migration notes (lessons learned, gotchas)
|
||||
|
||||
### 13.2 Clean Up React Files
|
||||
- [ ] Archive React project:
|
||||
- Option A: Move to `archive/react-version/`
|
||||
- Option B: Create git tag `pre-blazor-migration` and delete
|
||||
- Option C: Keep in separate branch
|
||||
- [ ] Remove Node.js files from root:
|
||||
- Delete `src/Client/package.json`
|
||||
- Delete `src/Client/package-lock.json`
|
||||
- Delete `src/Client/node_modules/`
|
||||
- Delete `src/Client/tsconfig*.json`
|
||||
- Delete `src/Client/vite.config.ts`
|
||||
- Delete `src/Client/tailwind.config.js`
|
||||
- Delete `src/Client/postcss.config.js`
|
||||
- Delete `src/Client/.eslintrc.cjs`
|
||||
- [ ] Update `.gitignore` (remove Node.js entries)
|
||||
|
||||
### 13.3 Code Quality
|
||||
- [ ] Run `dotnet format` on all files
|
||||
- [ ] Add XML documentation comments to public components
|
||||
- [ ] Ensure consistent naming conventions
|
||||
- [ ] Remove unused using statements
|
||||
- [ ] Remove commented-out code
|
||||
|
||||
---
|
||||
|
||||
## Phase 14: Production Deployment
|
||||
|
||||
### 14.1 Pre-Deployment Checklist
|
||||
- [ ] All components migrated and tested ✓
|
||||
- [ ] All routes working ✓
|
||||
- [ ] Mobile menu functional ✓
|
||||
- [ ] Tabs functional ✓
|
||||
- [ ] Analytics configured ✓
|
||||
- [ ] SEO tags verified ✓
|
||||
- [ ] Performance acceptable ✓
|
||||
- [ ] No console errors ✓
|
||||
- [ ] Cross-browser tested ✓
|
||||
|
||||
### 14.2 Deploy to Production
|
||||
- [ ] Merge `blazor-refactor` branch to `main`
|
||||
- [ ] Monitor GitHub Actions workflow
|
||||
- [ ] Verify deployment succeeds
|
||||
- [ ] Test production site at beaufindlay.com
|
||||
|
||||
### 14.3 Post-Deployment
|
||||
- [ ] Verify site loads correctly in production
|
||||
- [ ] Test all functionality in production
|
||||
- [ ] Verify analytics tracking
|
||||
- [ ] Monitor for errors (first 24-48 hours)
|
||||
- [ ] Check browser console for any warnings
|
||||
- [ ] Verify SSL certificate
|
||||
- [ ] Test social media sharing previews
|
||||
|
||||
---
|
||||
|
||||
## Component Migration Checklist
|
||||
|
||||
### Pages (5)
|
||||
- [ ] Layout (MainLayout.razor)
|
||||
- [ ] Home (Pages/Home.razor)
|
||||
- [ ] Work (Pages/Work.razor)
|
||||
- [ ] About (Pages/About.razor)
|
||||
- [ ] Error/404 (Pages/NotFound.razor)
|
||||
|
||||
### Typography Components (7)
|
||||
- [ ] Title.razor
|
||||
- [ ] Subtitle.razor
|
||||
- [ ] Text.razor
|
||||
- [ ] Label.razor
|
||||
- [ ] List.razor
|
||||
- [ ] ListItem.razor
|
||||
- [ ] AnchorLink.razor
|
||||
|
||||
### Form Components (3)
|
||||
- [ ] Button.razor
|
||||
- [ ] TextInput.razor
|
||||
- [ ] TextAreaInput.razor
|
||||
|
||||
### Display Components (5)
|
||||
- [ ] TechIcons.razor
|
||||
- [ ] SocialIcons.razor
|
||||
- [ ] WorkTimeline.razor
|
||||
- [ ] Loading.razor
|
||||
- [ ] LoadingSpinner.razor
|
||||
|
||||
### Feature Components (3)
|
||||
- [ ] NavBar.razor (in Shared/)
|
||||
- [ ] Footer.razor (in Shared/)
|
||||
- [ ] ContactMe.razor
|
||||
- [ ] AboutTabs.razor
|
||||
|
||||
### Shared/Infrastructure (2)
|
||||
- [ ] Icon.razor (new - SVG icon system)
|
||||
- [ ] CssHelper.cs (optional - CSS class utilities)
|
||||
|
||||
**Total: 25 components**
|
||||
|
||||
---
|
||||
|
||||
## CSS File Structure
|
||||
|
||||
```
|
||||
wwwroot/
|
||||
├── css/
|
||||
│ ├── variables.css # CSS custom properties (design tokens)
|
||||
│ ├── reset.css # Modern CSS reset
|
||||
│ ├── base.css # Base typography and body styles
|
||||
│ ├── layout.css # Layout utilities (flex, grid, container)
|
||||
│ ├── components.css # Component-specific styles
|
||||
│ ├── animations.css # Animations and transitions
|
||||
│ └── app.css # Main file that imports all others
|
||||
├── logo.webp
|
||||
├── robots.txt
|
||||
└── index.html
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key Syntax Conversions
|
||||
|
||||
| React/JSX | Blazor/Razor |
|
||||
|-----------|--------------|
|
||||
| `className="..."` | `class="..."` |
|
||||
| `{variable}` | `@variable` |
|
||||
| `{condition && <Element />}` | `@if (condition) { <Element /> }` |
|
||||
| `{items.map(item => ...)}` | `@foreach (var item in items) { ... }` |
|
||||
| `const [state, setState] = useState()` | `private bool state;` + `StateHasChanged()` |
|
||||
| `onClick={handler}` | `@onclick="Handler"` |
|
||||
| `onChange={handler}` | `@onchange="Handler"` |
|
||||
| `<Component prop={value} />` | `<Component Prop="@value" />` |
|
||||
| Props interface | `[Parameter]` properties |
|
||||
| `import Component from './Component'` | `@using` or implicit |
|
||||
|
||||
---
|
||||
|
||||
## Dependencies Eliminated
|
||||
|
||||
### Removed Libraries
|
||||
- ❌ Tailwind CSS → ✅ Vanilla CSS
|
||||
- ❌ PostCSS → ✅ None
|
||||
- ❌ Autoprefixer → ✅ Modern browsers only
|
||||
- ❌ React Icons → ✅ Inline SVG
|
||||
- ❌ Headless UI → ✅ Native HTML + CSS
|
||||
- ❌ React Router DOM → ✅ Blazor Router (built-in)
|
||||
- ❌ Vite → ✅ .NET SDK
|
||||
- ❌ TypeScript → ✅ C#
|
||||
- ❌ ESLint → ✅ Roslyn analyzers (built-in)
|
||||
- ❌ Node.js → ✅ None
|
||||
|
||||
### Added Technology
|
||||
- ✅ Static server-side rendering (Blazor SSR mode)
|
||||
- ✅ Pure CSS interactivity techniques (checkbox hack, radio buttons, :target pseudo-class)
|
||||
|
||||
### Build Dependencies
|
||||
- Before: Node.js, npm, Vite, TypeScript compiler, Tailwind CLI
|
||||
- After: .NET SDK only
|
||||
|
||||
### Hosting Requirements
|
||||
- Before: Static hosting (Azure Static Web Apps, any CDN)
|
||||
- After: ASP.NET Core server (Azure App Service, Container Apps, or any host supporting .NET)
|
||||
|
||||
---
|
||||
|
||||
## Risk Assessment
|
||||
|
||||
### High Risk (Requires Testing)
|
||||
- **Mobile menu with CSS checkbox hack:** CSS-only implementation complexity
|
||||
- *Mitigation:* Well-established pattern, test thoroughly across browsers
|
||||
- **Tabs with CSS (radio buttons or :target):** CSS-only implementation complexity
|
||||
- *Mitigation:* Test both approaches, choose most accessible
|
||||
- **Icon system:** 11 icons need SVG paths
|
||||
- *Mitigation:* Download from FontAwesome/Simple Icons, test early
|
||||
- **CSS-only accessibility:** Ensuring keyboard navigation works properly
|
||||
- *Mitigation:* Thorough accessibility testing with screen readers
|
||||
|
||||
### Medium Risk
|
||||
- **CSS conversion from Tailwind:** Large effort
|
||||
- *Mitigation:* Component-specific CSS, test each component
|
||||
- **Server hosting:** Requires server infrastructure instead of static hosting
|
||||
- *Mitigation:* Azure App Service is straightforward to configure
|
||||
- **Browser compatibility for CSS tricks:** Checkbox hack and advanced selectors
|
||||
- *Mitigation:* Test on all major browsers, provide fallbacks if needed
|
||||
|
||||
### Low Risk
|
||||
- **Basic component migration:** Straightforward
|
||||
- **Routing:** Blazor router is similar to React Router
|
||||
- **Static assets:** Simple copy operation
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- [ ] Zero npm/Node.js dependencies
|
||||
- [ ] Zero CSS framework dependencies
|
||||
- [ ] Zero JavaScript (pure CSS interactivity)
|
||||
- [ ] All pages render identically to React version
|
||||
- [ ] Mobile menu works smoothly (CSS checkbox hack)
|
||||
- [ ] Tabs work smoothly (CSS radio buttons or :target)
|
||||
- [ ] Site loads in < 2 seconds on 4G (server-rendered)
|
||||
- [ ] Site works with JavaScript disabled
|
||||
- [ ] No WebSocket connections present
|
||||
- [ ] No SignalR scripts loaded
|
||||
- [ ] No JavaScript files served
|
||||
- [ ] Analytics functional (server-side or noscript fallback)
|
||||
- [ ] SEO tags correct
|
||||
- [ ] Mobile responsive
|
||||
- [ ] Cross-browser compatible (including CSS-only features)
|
||||
- [ ] Keyboard accessible (Tab/Enter/Space navigation)
|
||||
- [ ] Lighthouse score: 95+ (Performance, Accessibility, SEO)
|
||||
- [ ] Server resource usage minimal (stateless requests only)
|
||||
|
||||
---
|
||||
|
||||
## Estimated Timeline
|
||||
|
||||
- **Phase 1-2 (Setup & CSS):** 2-3 days
|
||||
- **Phase 3 (Icons):** 0.5-1 day
|
||||
- **Phase 4 (Core Structure):** 1-2 days
|
||||
- **Phase 5-6 (Pages & Components):** 3-4 days
|
||||
- **Phase 7 (Interactive - CSS only):** 1-2 days
|
||||
- **Phase 8 (CSS Conversion):** 2-3 days
|
||||
- **Phase 9 (SEO & Analytics):** 0.5-1 day
|
||||
- **Phase 10-11 (Build & Deploy):** 1-2 days (server configuration)
|
||||
- **Phase 12 (Testing):** 2-3 days (including CSS-only interactivity testing)
|
||||
- **Phase 13-14 (Docs & Deploy):** 1 day
|
||||
|
||||
**Total: 14-22 days** (depending on CSS approach and server setup complexity)
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- This plan prioritizes **simplicity** and **maintainability** over feature richness
|
||||
- No external dependencies means **no breaking changes** from library updates
|
||||
- Vanilla CSS may take longer initially but is **easier to maintain** long-term
|
||||
- Static SSR provides **instant page loads** with server-side rendering and excellent SEO
|
||||
- **Zero JavaScript** - pure CSS interactivity (checkbox hack, radio buttons) - **no framework hydration, no parsing overhead**
|
||||
- The site will be **future-proof** with minimal maintenance requirements
|
||||
- Focus on **modern CSS features** (Grid, Flexbox, Custom Properties) rather than utility classes
|
||||
- Test frequently throughout migration - **don't wait until the end**
|
||||
- **Tradeoff:** Requires server hosting instead of static hosting, but provides better initial load performance
|
||||
- **Key Benefits:**
|
||||
- No WebSocket connections = lower server resource usage, simpler architecture, no reconnection issues
|
||||
- No JavaScript = works with JS disabled, faster TTI, smaller payload, privacy-friendly
|
||||
- Accessible by default (native HTML form controls)
|
||||
5
my-portfolio.slnx
Normal file
5
my-portfolio.slnx
Normal file
@@ -0,0 +1,5 @@
|
||||
<Solution>
|
||||
<Folder Name="/src/">
|
||||
<Project Path="src/BlazorApp/BlazorApp.csproj" />
|
||||
</Folder>
|
||||
</Solution>
|
||||
10
src/BlazorApp/BlazorApp.csproj
Normal file
10
src/BlazorApp/BlazorApp.csproj
Normal file
@@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
22
src/BlazorApp/Components/App.razor
Normal file
22
src/BlazorApp/Components/App.razor
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<base href="/" />
|
||||
<ResourcePreloader />
|
||||
<link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]" />
|
||||
<link rel="stylesheet" href="@Assets["app.css"]" />
|
||||
<link rel="stylesheet" href="@Assets["BlazorApp.styles.css"]" />
|
||||
<ImportMap />
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
<HeadOutlet />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<Routes />
|
||||
<script src="@Assets["_framework/blazor.web.js"]"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
17
src/BlazorApp/Components/Layout/MainLayout.razor
Normal file
17
src/BlazorApp/Components/Layout/MainLayout.razor
Normal file
@@ -0,0 +1,17 @@
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<div class="page">
|
||||
<div class="sidebar">
|
||||
<NavMenu />
|
||||
</div>
|
||||
|
||||
<main>
|
||||
<div class="top-row px-4">
|
||||
<a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
|
||||
</div>
|
||||
|
||||
<article class="content px-4">
|
||||
@Body
|
||||
</article>
|
||||
</main>
|
||||
</div>
|
||||
98
src/BlazorApp/Components/Layout/MainLayout.razor.css
Normal file
98
src/BlazorApp/Components/Layout/MainLayout.razor.css
Normal file
@@ -0,0 +1,98 @@
|
||||
.page {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
background-color: #f7f7f7;
|
||||
border-bottom: 1px solid #d6d5d5;
|
||||
justify-content: flex-end;
|
||||
height: 3.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row ::deep .btn-link {
|
||||
white-space: nowrap;
|
||||
margin-left: 1.5rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.top-row ::deep a:first-child {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@media (max-width: 640.98px) {
|
||||
.top-row {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row ::deep .btn-link {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.page {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.top-row {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.top-row.auth ::deep a:first-child {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.top-row, article {
|
||||
padding-left: 2rem !important;
|
||||
padding-right: 1.5rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
#blazor-error-ui {
|
||||
color-scheme: light only;
|
||||
background: lightyellow;
|
||||
bottom: 0;
|
||||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
|
||||
box-sizing: border-box;
|
||||
display: none;
|
||||
left: 0;
|
||||
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#blazor-error-ui .dismiss {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
top: 0.5rem;
|
||||
}
|
||||
24
src/BlazorApp/Components/Layout/NavMenu.razor
Normal file
24
src/BlazorApp/Components/Layout/NavMenu.razor
Normal file
@@ -0,0 +1,24 @@
|
||||
<div class="top-row ps-3 navbar navbar-dark">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="">BlazorApp</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="checkbox" title="Navigation menu" class="navbar-toggler" />
|
||||
|
||||
<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
|
||||
<nav class="nav flex-column">
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
|
||||
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
|
||||
</NavLink>
|
||||
</div>
|
||||
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="weather">
|
||||
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Weather
|
||||
</NavLink>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
105
src/BlazorApp/Components/Layout/NavMenu.razor.css
Normal file
105
src/BlazorApp/Components/Layout/NavMenu.razor.css
Normal file
@@ -0,0 +1,105 @@
|
||||
.navbar-toggler {
|
||||
appearance: none;
|
||||
cursor: pointer;
|
||||
width: 3.5rem;
|
||||
height: 2.5rem;
|
||||
color: white;
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 1rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.navbar-toggler:checked {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
min-height: 3.5rem;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.bi {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
margin-right: 0.75rem;
|
||||
top: -1px;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.bi-house-door-fill-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-plus-square-fill-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-list-nested-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
font-size: 0.9rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-item:first-of-type {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.nav-item:last-of-type {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.nav-item ::deep .nav-link {
|
||||
color: #d7d7d7;
|
||||
background: none;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
height: 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 3rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.nav-item ::deep a.active {
|
||||
background-color: rgba(255,255,255,0.37);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-item ::deep .nav-link:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-scrollable {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navbar-toggler:checked ~ .nav-scrollable {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.navbar-toggler {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-scrollable {
|
||||
/* Never collapse the sidebar for wide screens */
|
||||
display: block;
|
||||
|
||||
/* Allow sidebar to scroll for tall menus */
|
||||
height: calc(100vh - 3.5rem);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
36
src/BlazorApp/Components/Pages/Error.razor
Normal file
36
src/BlazorApp/Components/Pages/Error.razor
Normal file
@@ -0,0 +1,36 @@
|
||||
@page "/Error"
|
||||
@using System.Diagnostics
|
||||
|
||||
<PageTitle>Error</PageTitle>
|
||||
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
@if (ShowRequestId)
|
||||
{
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@RequestId</code>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||
It can result in displaying sensitive information from exceptions to end users.
|
||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||
and restarting the app.
|
||||
</p>
|
||||
|
||||
@code{
|
||||
[CascadingParameter]
|
||||
private HttpContext? HttpContext { get; set; }
|
||||
|
||||
private string? RequestId { get; set; }
|
||||
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
protected override void OnInitialized() =>
|
||||
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
|
||||
}
|
||||
7
src/BlazorApp/Components/Pages/Home.razor
Normal file
7
src/BlazorApp/Components/Pages/Home.razor
Normal file
@@ -0,0 +1,7 @@
|
||||
@page "/"
|
||||
|
||||
<PageTitle>Home</PageTitle>
|
||||
|
||||
<h1>Hello, world!</h1>
|
||||
|
||||
Welcome to your new app.
|
||||
5
src/BlazorApp/Components/Pages/NotFound.razor
Normal file
5
src/BlazorApp/Components/Pages/NotFound.razor
Normal file
@@ -0,0 +1,5 @@
|
||||
@page "/not-found"
|
||||
@layout MainLayout
|
||||
|
||||
<h3>Not Found</h3>
|
||||
<p>Sorry, the content you are looking for does not exist.</p>
|
||||
64
src/BlazorApp/Components/Pages/Weather.razor
Normal file
64
src/BlazorApp/Components/Pages/Weather.razor
Normal file
@@ -0,0 +1,64 @@
|
||||
@page "/weather"
|
||||
@attribute [StreamRendering]
|
||||
|
||||
<PageTitle>Weather</PageTitle>
|
||||
|
||||
<h1>Weather</h1>
|
||||
|
||||
<p>This component demonstrates showing data.</p>
|
||||
|
||||
@if (forecasts == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th aria-label="Temperature in Celsius">Temp. (C)</th>
|
||||
<th aria-label="Temperature in Fahrenheit">Temp. (F)</th>
|
||||
<th>Summary</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var forecast in forecasts)
|
||||
{
|
||||
<tr>
|
||||
<td>@forecast.Date.ToShortDateString()</td>
|
||||
<td>@forecast.TemperatureC</td>
|
||||
<td>@forecast.TemperatureF</td>
|
||||
<td>@forecast.Summary</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
|
||||
@code {
|
||||
private WeatherForecast[]? forecasts;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// Simulate asynchronous loading to demonstrate streaming rendering
|
||||
await Task.Delay(500);
|
||||
|
||||
var startDate = DateOnly.FromDateTime(DateTime.Now);
|
||||
var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" };
|
||||
forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||
{
|
||||
Date = startDate.AddDays(index),
|
||||
TemperatureC = Random.Shared.Next(-20, 55),
|
||||
Summary = summaries[Random.Shared.Next(summaries.Length)]
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
private class WeatherForecast
|
||||
{
|
||||
public DateOnly Date { get; set; }
|
||||
public int TemperatureC { get; set; }
|
||||
public string? Summary { get; set; }
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
}
|
||||
}
|
||||
6
src/BlazorApp/Components/Routes.razor
Normal file
6
src/BlazorApp/Components/Routes.razor
Normal file
@@ -0,0 +1,6 @@
|
||||
<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
|
||||
<FocusOnNavigate RouteData="routeData" Selector="h1" />
|
||||
</Found>
|
||||
</Router>
|
||||
11
src/BlazorApp/Components/_Imports.razor
Normal file
11
src/BlazorApp/Components/_Imports.razor
Normal file
@@ -0,0 +1,11 @@
|
||||
@using System.Net.Http
|
||||
@using System.Net.Http.Json
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.JSInterop
|
||||
@using BlazorApp
|
||||
@using BlazorApp.Components
|
||||
@using BlazorApp.Components.Layout
|
||||
25
src/BlazorApp/Program.cs
Normal file
25
src/BlazorApp/Program.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using BlazorApp.Components;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddRazorComponents();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseAntiforgery();
|
||||
|
||||
app.MapStaticAssets();
|
||||
app.MapRazorComponents<App>();
|
||||
|
||||
app.Run();
|
||||
23
src/BlazorApp/Properties/launchSettings.json
Normal file
23
src/BlazorApp/Properties/launchSettings.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5064",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:7162;http://localhost:5064",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
src/BlazorApp/appsettings.Development.json
Normal file
8
src/BlazorApp/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/BlazorApp/appsettings.json
Normal file
9
src/BlazorApp/appsettings.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
60
src/BlazorApp/wwwroot/app.css
Normal file
60
src/BlazorApp/wwwroot/app.css
Normal file
@@ -0,0 +1,60 @@
|
||||
html, body {
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
a, .btn-link {
|
||||
color: #006bb7;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
}
|
||||
|
||||
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
|
||||
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-top: 1.1rem;
|
||||
}
|
||||
|
||||
h1:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.valid.modified:not([type=checkbox]) {
|
||||
outline: 1px solid #26b050;
|
||||
}
|
||||
|
||||
.invalid {
|
||||
outline: 1px solid #e50000;
|
||||
}
|
||||
|
||||
.validation-message {
|
||||
color: #e50000;
|
||||
}
|
||||
|
||||
.blazor-error-boundary {
|
||||
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
|
||||
padding: 1rem 1rem 1rem 3.7rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.blazor-error-boundary::after {
|
||||
content: "An error has occurred."
|
||||
}
|
||||
|
||||
.darker-border-checkbox.form-check-input {
|
||||
border-color: #929292;
|
||||
}
|
||||
|
||||
.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
|
||||
color: var(--bs-secondary-color);
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
|
||||
text-align: start;
|
||||
}
|
||||
BIN
src/BlazorApp/wwwroot/favicon.png
Normal file
BIN
src/BlazorApp/wwwroot/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
4085
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css
vendored
Normal file
4085
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css
vendored
Normal file
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
4084
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css
vendored
Normal file
4084
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css
vendored
Normal file
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
597
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css
vendored
Normal file
597
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css
vendored
Normal file
@@ -0,0 +1,597 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v5.3.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2024 The Bootstrap Authors
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/
|
||||
:root,
|
||||
[data-bs-theme=light] {
|
||||
--bs-blue: #0d6efd;
|
||||
--bs-indigo: #6610f2;
|
||||
--bs-purple: #6f42c1;
|
||||
--bs-pink: #d63384;
|
||||
--bs-red: #dc3545;
|
||||
--bs-orange: #fd7e14;
|
||||
--bs-yellow: #ffc107;
|
||||
--bs-green: #198754;
|
||||
--bs-teal: #20c997;
|
||||
--bs-cyan: #0dcaf0;
|
||||
--bs-black: #000;
|
||||
--bs-white: #fff;
|
||||
--bs-gray: #6c757d;
|
||||
--bs-gray-dark: #343a40;
|
||||
--bs-gray-100: #f8f9fa;
|
||||
--bs-gray-200: #e9ecef;
|
||||
--bs-gray-300: #dee2e6;
|
||||
--bs-gray-400: #ced4da;
|
||||
--bs-gray-500: #adb5bd;
|
||||
--bs-gray-600: #6c757d;
|
||||
--bs-gray-700: #495057;
|
||||
--bs-gray-800: #343a40;
|
||||
--bs-gray-900: #212529;
|
||||
--bs-primary: #0d6efd;
|
||||
--bs-secondary: #6c757d;
|
||||
--bs-success: #198754;
|
||||
--bs-info: #0dcaf0;
|
||||
--bs-warning: #ffc107;
|
||||
--bs-danger: #dc3545;
|
||||
--bs-light: #f8f9fa;
|
||||
--bs-dark: #212529;
|
||||
--bs-primary-rgb: 13, 110, 253;
|
||||
--bs-secondary-rgb: 108, 117, 125;
|
||||
--bs-success-rgb: 25, 135, 84;
|
||||
--bs-info-rgb: 13, 202, 240;
|
||||
--bs-warning-rgb: 255, 193, 7;
|
||||
--bs-danger-rgb: 220, 53, 69;
|
||||
--bs-light-rgb: 248, 249, 250;
|
||||
--bs-dark-rgb: 33, 37, 41;
|
||||
--bs-primary-text-emphasis: #052c65;
|
||||
--bs-secondary-text-emphasis: #2b2f32;
|
||||
--bs-success-text-emphasis: #0a3622;
|
||||
--bs-info-text-emphasis: #055160;
|
||||
--bs-warning-text-emphasis: #664d03;
|
||||
--bs-danger-text-emphasis: #58151c;
|
||||
--bs-light-text-emphasis: #495057;
|
||||
--bs-dark-text-emphasis: #495057;
|
||||
--bs-primary-bg-subtle: #cfe2ff;
|
||||
--bs-secondary-bg-subtle: #e2e3e5;
|
||||
--bs-success-bg-subtle: #d1e7dd;
|
||||
--bs-info-bg-subtle: #cff4fc;
|
||||
--bs-warning-bg-subtle: #fff3cd;
|
||||
--bs-danger-bg-subtle: #f8d7da;
|
||||
--bs-light-bg-subtle: #fcfcfd;
|
||||
--bs-dark-bg-subtle: #ced4da;
|
||||
--bs-primary-border-subtle: #9ec5fe;
|
||||
--bs-secondary-border-subtle: #c4c8cb;
|
||||
--bs-success-border-subtle: #a3cfbb;
|
||||
--bs-info-border-subtle: #9eeaf9;
|
||||
--bs-warning-border-subtle: #ffe69c;
|
||||
--bs-danger-border-subtle: #f1aeb5;
|
||||
--bs-light-border-subtle: #e9ecef;
|
||||
--bs-dark-border-subtle: #adb5bd;
|
||||
--bs-white-rgb: 255, 255, 255;
|
||||
--bs-black-rgb: 0, 0, 0;
|
||||
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||
--bs-body-font-size: 1rem;
|
||||
--bs-body-font-weight: 400;
|
||||
--bs-body-line-height: 1.5;
|
||||
--bs-body-color: #212529;
|
||||
--bs-body-color-rgb: 33, 37, 41;
|
||||
--bs-body-bg: #fff;
|
||||
--bs-body-bg-rgb: 255, 255, 255;
|
||||
--bs-emphasis-color: #000;
|
||||
--bs-emphasis-color-rgb: 0, 0, 0;
|
||||
--bs-secondary-color: rgba(33, 37, 41, 0.75);
|
||||
--bs-secondary-color-rgb: 33, 37, 41;
|
||||
--bs-secondary-bg: #e9ecef;
|
||||
--bs-secondary-bg-rgb: 233, 236, 239;
|
||||
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
|
||||
--bs-tertiary-color-rgb: 33, 37, 41;
|
||||
--bs-tertiary-bg: #f8f9fa;
|
||||
--bs-tertiary-bg-rgb: 248, 249, 250;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #0d6efd;
|
||||
--bs-link-color-rgb: 13, 110, 253;
|
||||
--bs-link-decoration: underline;
|
||||
--bs-link-hover-color: #0a58ca;
|
||||
--bs-link-hover-color-rgb: 10, 88, 202;
|
||||
--bs-code-color: #d63384;
|
||||
--bs-highlight-color: #212529;
|
||||
--bs-highlight-bg: #fff3cd;
|
||||
--bs-border-width: 1px;
|
||||
--bs-border-style: solid;
|
||||
--bs-border-color: #dee2e6;
|
||||
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
|
||||
--bs-border-radius: 0.375rem;
|
||||
--bs-border-radius-sm: 0.25rem;
|
||||
--bs-border-radius-lg: 0.5rem;
|
||||
--bs-border-radius-xl: 1rem;
|
||||
--bs-border-radius-xxl: 2rem;
|
||||
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
|
||||
--bs-border-radius-pill: 50rem;
|
||||
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||||
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||||
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
|
||||
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
--bs-focus-ring-width: 0.25rem;
|
||||
--bs-focus-ring-opacity: 0.25;
|
||||
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
|
||||
--bs-form-valid-color: #198754;
|
||||
--bs-form-valid-border-color: #198754;
|
||||
--bs-form-invalid-color: #dc3545;
|
||||
--bs-form-invalid-border-color: #dc3545;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] {
|
||||
color-scheme: dark;
|
||||
--bs-body-color: #dee2e6;
|
||||
--bs-body-color-rgb: 222, 226, 230;
|
||||
--bs-body-bg: #212529;
|
||||
--bs-body-bg-rgb: 33, 37, 41;
|
||||
--bs-emphasis-color: #fff;
|
||||
--bs-emphasis-color-rgb: 255, 255, 255;
|
||||
--bs-secondary-color: rgba(222, 226, 230, 0.75);
|
||||
--bs-secondary-color-rgb: 222, 226, 230;
|
||||
--bs-secondary-bg: #343a40;
|
||||
--bs-secondary-bg-rgb: 52, 58, 64;
|
||||
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||
--bs-tertiary-bg: #2b3035;
|
||||
--bs-tertiary-bg-rgb: 43, 48, 53;
|
||||
--bs-primary-text-emphasis: #6ea8fe;
|
||||
--bs-secondary-text-emphasis: #a7acb1;
|
||||
--bs-success-text-emphasis: #75b798;
|
||||
--bs-info-text-emphasis: #6edff6;
|
||||
--bs-warning-text-emphasis: #ffda6a;
|
||||
--bs-danger-text-emphasis: #ea868f;
|
||||
--bs-light-text-emphasis: #f8f9fa;
|
||||
--bs-dark-text-emphasis: #dee2e6;
|
||||
--bs-primary-bg-subtle: #031633;
|
||||
--bs-secondary-bg-subtle: #161719;
|
||||
--bs-success-bg-subtle: #051b11;
|
||||
--bs-info-bg-subtle: #032830;
|
||||
--bs-warning-bg-subtle: #332701;
|
||||
--bs-danger-bg-subtle: #2c0b0e;
|
||||
--bs-light-bg-subtle: #343a40;
|
||||
--bs-dark-bg-subtle: #1a1d20;
|
||||
--bs-primary-border-subtle: #084298;
|
||||
--bs-secondary-border-subtle: #41464b;
|
||||
--bs-success-border-subtle: #0f5132;
|
||||
--bs-info-border-subtle: #087990;
|
||||
--bs-warning-border-subtle: #997404;
|
||||
--bs-danger-border-subtle: #842029;
|
||||
--bs-light-border-subtle: #495057;
|
||||
--bs-dark-border-subtle: #343a40;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #6ea8fe;
|
||||
--bs-link-hover-color: #8bb9fe;
|
||||
--bs-link-color-rgb: 110, 168, 254;
|
||||
--bs-link-hover-color-rgb: 139, 185, 254;
|
||||
--bs-code-color: #e685b5;
|
||||
--bs-highlight-color: #dee2e6;
|
||||
--bs-highlight-bg: #664d03;
|
||||
--bs-border-color: #495057;
|
||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||
--bs-form-valid-color: #75b798;
|
||||
--bs-form-valid-border-color: #75b798;
|
||||
--bs-form-invalid-color: #ea868f;
|
||||
--bs-form-invalid-border-color: #ea868f;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--bs-body-font-family);
|
||||
font-size: var(--bs-body-font-size);
|
||||
font-weight: var(--bs-body-font-weight);
|
||||
line-height: var(--bs-body-line-height);
|
||||
color: var(--bs-body-color);
|
||||
text-align: var(--bs-body-text-align);
|
||||
background-color: var(--bs-body-bg);
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
border: 0;
|
||||
border-top: var(--bs-border-width) solid;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
h6, h5, h4, h3, h2, h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
color: var(--bs-heading-color);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title] {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.1875em;
|
||||
color: var(--bs-highlight-color);
|
||||
background-color: var(--bs-highlight-bg);
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover {
|
||||
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
|
||||
}
|
||||
|
||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: var(--bs-font-monospace);
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
pre code {
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-code-color);
|
||||
word-wrap: break-word;
|
||||
}
|
||||
a > code {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
kbd {
|
||||
padding: 0.1875rem 0.375rem;
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-body-bg);
|
||||
background-color: var(--bs-body-color);
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
kbd kbd {
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: var(--bs-secondary-color);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
}
|
||||
|
||||
thead,
|
||||
tbody,
|
||||
tfoot,
|
||||
tr,
|
||||
td,
|
||||
th {
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
select:disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
button,
|
||||
[type=button],
|
||||
[type=reset],
|
||||
[type=submit] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
button:not(:disabled),
|
||||
[type=button]:not(:disabled),
|
||||
[type=reset]:not(:disabled),
|
||||
[type=submit]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
float: left;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
line-height: inherit;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
legend + * {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper,
|
||||
::-webkit-datetime-edit-text,
|
||||
::-webkit-datetime-edit-minute,
|
||||
::-webkit-datetime-edit-hour-field,
|
||||
::-webkit-datetime-edit-day-field,
|
||||
::-webkit-datetime-edit-month-field,
|
||||
::-webkit-datetime-edit-year-field {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-inner-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type=search] {
|
||||
-webkit-appearance: textfield;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
/* rtl:raw:
|
||||
[type="tel"],
|
||||
[type="url"],
|
||||
[type="email"],
|
||||
[type="number"] {
|
||||
direction: ltr;
|
||||
}
|
||||
*/
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
::file-selector-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=bootstrap-reboot.css.map */
|
||||
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css
vendored
Normal file
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
594
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css
vendored
Normal file
594
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css
vendored
Normal file
@@ -0,0 +1,594 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v5.3.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2024 The Bootstrap Authors
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/
|
||||
:root,
|
||||
[data-bs-theme=light] {
|
||||
--bs-blue: #0d6efd;
|
||||
--bs-indigo: #6610f2;
|
||||
--bs-purple: #6f42c1;
|
||||
--bs-pink: #d63384;
|
||||
--bs-red: #dc3545;
|
||||
--bs-orange: #fd7e14;
|
||||
--bs-yellow: #ffc107;
|
||||
--bs-green: #198754;
|
||||
--bs-teal: #20c997;
|
||||
--bs-cyan: #0dcaf0;
|
||||
--bs-black: #000;
|
||||
--bs-white: #fff;
|
||||
--bs-gray: #6c757d;
|
||||
--bs-gray-dark: #343a40;
|
||||
--bs-gray-100: #f8f9fa;
|
||||
--bs-gray-200: #e9ecef;
|
||||
--bs-gray-300: #dee2e6;
|
||||
--bs-gray-400: #ced4da;
|
||||
--bs-gray-500: #adb5bd;
|
||||
--bs-gray-600: #6c757d;
|
||||
--bs-gray-700: #495057;
|
||||
--bs-gray-800: #343a40;
|
||||
--bs-gray-900: #212529;
|
||||
--bs-primary: #0d6efd;
|
||||
--bs-secondary: #6c757d;
|
||||
--bs-success: #198754;
|
||||
--bs-info: #0dcaf0;
|
||||
--bs-warning: #ffc107;
|
||||
--bs-danger: #dc3545;
|
||||
--bs-light: #f8f9fa;
|
||||
--bs-dark: #212529;
|
||||
--bs-primary-rgb: 13, 110, 253;
|
||||
--bs-secondary-rgb: 108, 117, 125;
|
||||
--bs-success-rgb: 25, 135, 84;
|
||||
--bs-info-rgb: 13, 202, 240;
|
||||
--bs-warning-rgb: 255, 193, 7;
|
||||
--bs-danger-rgb: 220, 53, 69;
|
||||
--bs-light-rgb: 248, 249, 250;
|
||||
--bs-dark-rgb: 33, 37, 41;
|
||||
--bs-primary-text-emphasis: #052c65;
|
||||
--bs-secondary-text-emphasis: #2b2f32;
|
||||
--bs-success-text-emphasis: #0a3622;
|
||||
--bs-info-text-emphasis: #055160;
|
||||
--bs-warning-text-emphasis: #664d03;
|
||||
--bs-danger-text-emphasis: #58151c;
|
||||
--bs-light-text-emphasis: #495057;
|
||||
--bs-dark-text-emphasis: #495057;
|
||||
--bs-primary-bg-subtle: #cfe2ff;
|
||||
--bs-secondary-bg-subtle: #e2e3e5;
|
||||
--bs-success-bg-subtle: #d1e7dd;
|
||||
--bs-info-bg-subtle: #cff4fc;
|
||||
--bs-warning-bg-subtle: #fff3cd;
|
||||
--bs-danger-bg-subtle: #f8d7da;
|
||||
--bs-light-bg-subtle: #fcfcfd;
|
||||
--bs-dark-bg-subtle: #ced4da;
|
||||
--bs-primary-border-subtle: #9ec5fe;
|
||||
--bs-secondary-border-subtle: #c4c8cb;
|
||||
--bs-success-border-subtle: #a3cfbb;
|
||||
--bs-info-border-subtle: #9eeaf9;
|
||||
--bs-warning-border-subtle: #ffe69c;
|
||||
--bs-danger-border-subtle: #f1aeb5;
|
||||
--bs-light-border-subtle: #e9ecef;
|
||||
--bs-dark-border-subtle: #adb5bd;
|
||||
--bs-white-rgb: 255, 255, 255;
|
||||
--bs-black-rgb: 0, 0, 0;
|
||||
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||
--bs-body-font-size: 1rem;
|
||||
--bs-body-font-weight: 400;
|
||||
--bs-body-line-height: 1.5;
|
||||
--bs-body-color: #212529;
|
||||
--bs-body-color-rgb: 33, 37, 41;
|
||||
--bs-body-bg: #fff;
|
||||
--bs-body-bg-rgb: 255, 255, 255;
|
||||
--bs-emphasis-color: #000;
|
||||
--bs-emphasis-color-rgb: 0, 0, 0;
|
||||
--bs-secondary-color: rgba(33, 37, 41, 0.75);
|
||||
--bs-secondary-color-rgb: 33, 37, 41;
|
||||
--bs-secondary-bg: #e9ecef;
|
||||
--bs-secondary-bg-rgb: 233, 236, 239;
|
||||
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
|
||||
--bs-tertiary-color-rgb: 33, 37, 41;
|
||||
--bs-tertiary-bg: #f8f9fa;
|
||||
--bs-tertiary-bg-rgb: 248, 249, 250;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #0d6efd;
|
||||
--bs-link-color-rgb: 13, 110, 253;
|
||||
--bs-link-decoration: underline;
|
||||
--bs-link-hover-color: #0a58ca;
|
||||
--bs-link-hover-color-rgb: 10, 88, 202;
|
||||
--bs-code-color: #d63384;
|
||||
--bs-highlight-color: #212529;
|
||||
--bs-highlight-bg: #fff3cd;
|
||||
--bs-border-width: 1px;
|
||||
--bs-border-style: solid;
|
||||
--bs-border-color: #dee2e6;
|
||||
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
|
||||
--bs-border-radius: 0.375rem;
|
||||
--bs-border-radius-sm: 0.25rem;
|
||||
--bs-border-radius-lg: 0.5rem;
|
||||
--bs-border-radius-xl: 1rem;
|
||||
--bs-border-radius-xxl: 2rem;
|
||||
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
|
||||
--bs-border-radius-pill: 50rem;
|
||||
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||||
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||||
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
|
||||
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
--bs-focus-ring-width: 0.25rem;
|
||||
--bs-focus-ring-opacity: 0.25;
|
||||
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
|
||||
--bs-form-valid-color: #198754;
|
||||
--bs-form-valid-border-color: #198754;
|
||||
--bs-form-invalid-color: #dc3545;
|
||||
--bs-form-invalid-border-color: #dc3545;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] {
|
||||
color-scheme: dark;
|
||||
--bs-body-color: #dee2e6;
|
||||
--bs-body-color-rgb: 222, 226, 230;
|
||||
--bs-body-bg: #212529;
|
||||
--bs-body-bg-rgb: 33, 37, 41;
|
||||
--bs-emphasis-color: #fff;
|
||||
--bs-emphasis-color-rgb: 255, 255, 255;
|
||||
--bs-secondary-color: rgba(222, 226, 230, 0.75);
|
||||
--bs-secondary-color-rgb: 222, 226, 230;
|
||||
--bs-secondary-bg: #343a40;
|
||||
--bs-secondary-bg-rgb: 52, 58, 64;
|
||||
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||
--bs-tertiary-bg: #2b3035;
|
||||
--bs-tertiary-bg-rgb: 43, 48, 53;
|
||||
--bs-primary-text-emphasis: #6ea8fe;
|
||||
--bs-secondary-text-emphasis: #a7acb1;
|
||||
--bs-success-text-emphasis: #75b798;
|
||||
--bs-info-text-emphasis: #6edff6;
|
||||
--bs-warning-text-emphasis: #ffda6a;
|
||||
--bs-danger-text-emphasis: #ea868f;
|
||||
--bs-light-text-emphasis: #f8f9fa;
|
||||
--bs-dark-text-emphasis: #dee2e6;
|
||||
--bs-primary-bg-subtle: #031633;
|
||||
--bs-secondary-bg-subtle: #161719;
|
||||
--bs-success-bg-subtle: #051b11;
|
||||
--bs-info-bg-subtle: #032830;
|
||||
--bs-warning-bg-subtle: #332701;
|
||||
--bs-danger-bg-subtle: #2c0b0e;
|
||||
--bs-light-bg-subtle: #343a40;
|
||||
--bs-dark-bg-subtle: #1a1d20;
|
||||
--bs-primary-border-subtle: #084298;
|
||||
--bs-secondary-border-subtle: #41464b;
|
||||
--bs-success-border-subtle: #0f5132;
|
||||
--bs-info-border-subtle: #087990;
|
||||
--bs-warning-border-subtle: #997404;
|
||||
--bs-danger-border-subtle: #842029;
|
||||
--bs-light-border-subtle: #495057;
|
||||
--bs-dark-border-subtle: #343a40;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #6ea8fe;
|
||||
--bs-link-hover-color: #8bb9fe;
|
||||
--bs-link-color-rgb: 110, 168, 254;
|
||||
--bs-link-hover-color-rgb: 139, 185, 254;
|
||||
--bs-code-color: #e685b5;
|
||||
--bs-highlight-color: #dee2e6;
|
||||
--bs-highlight-bg: #664d03;
|
||||
--bs-border-color: #495057;
|
||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||
--bs-form-valid-color: #75b798;
|
||||
--bs-form-valid-border-color: #75b798;
|
||||
--bs-form-invalid-color: #ea868f;
|
||||
--bs-form-invalid-border-color: #ea868f;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--bs-body-font-family);
|
||||
font-size: var(--bs-body-font-size);
|
||||
font-weight: var(--bs-body-font-weight);
|
||||
line-height: var(--bs-body-line-height);
|
||||
color: var(--bs-body-color);
|
||||
text-align: var(--bs-body-text-align);
|
||||
background-color: var(--bs-body-bg);
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
border: 0;
|
||||
border-top: var(--bs-border-width) solid;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
h6, h5, h4, h3, h2, h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
color: var(--bs-heading-color);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title] {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.1875em;
|
||||
color: var(--bs-highlight-color);
|
||||
background-color: var(--bs-highlight-bg);
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover {
|
||||
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
|
||||
}
|
||||
|
||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: var(--bs-font-monospace);
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
pre code {
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-code-color);
|
||||
word-wrap: break-word;
|
||||
}
|
||||
a > code {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
kbd {
|
||||
padding: 0.1875rem 0.375rem;
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-body-bg);
|
||||
background-color: var(--bs-body-color);
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
kbd kbd {
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: var(--bs-secondary-color);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
}
|
||||
|
||||
thead,
|
||||
tbody,
|
||||
tfoot,
|
||||
tr,
|
||||
td,
|
||||
th {
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
select:disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
button,
|
||||
[type=button],
|
||||
[type=reset],
|
||||
[type=submit] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
button:not(:disabled),
|
||||
[type=button]:not(:disabled),
|
||||
[type=reset]:not(:disabled),
|
||||
[type=submit]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
float: right;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
line-height: inherit;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
legend + * {
|
||||
clear: right;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper,
|
||||
::-webkit-datetime-edit-text,
|
||||
::-webkit-datetime-edit-minute,
|
||||
::-webkit-datetime-edit-hour-field,
|
||||
::-webkit-datetime-edit-day-field,
|
||||
::-webkit-datetime-edit-month-field,
|
||||
::-webkit-datetime-edit-year-field {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-inner-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type=search] {
|
||||
-webkit-appearance: textfield;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
[type="tel"],
|
||||
[type="url"],
|
||||
[type="email"],
|
||||
[type="number"] {
|
||||
direction: ltr;
|
||||
}
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
::file-selector-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */
|
||||
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css
vendored
Normal file
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
5402
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css
vendored
Normal file
5402
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css
vendored
Normal file
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
5393
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css
vendored
Normal file
5393
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css
vendored
Normal file
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
12057
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.css
vendored
Normal file
12057
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css
vendored
Normal file
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
12030
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css
vendored
Normal file
12030
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css
vendored
Normal file
6
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6314
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js
vendored
Normal file
6314
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js
vendored
Normal file
7
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
4447
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js
vendored
Normal file
4447
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js
vendored
Normal file
7
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
4494
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.js
vendored
Normal file
4494
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js
vendored
Normal file
7
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map
vendored
Normal file
1
src/BlazorApp/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user