Fixed voice work supported language search. Include supported languages and original circle in the search result item. Several UI style updates.
This commit is contained in:
@@ -28,8 +28,10 @@ public record VoiceWorkSearchResult
|
||||
public byte SubtitleLanguage { get; init; }
|
||||
public bool? IsValid { get; init; }
|
||||
public required VoiceWorkCircleItem Circle { get; set; }
|
||||
public VoiceWorkCircleItem? OriginalCircle { get; set; }
|
||||
public VoiceWorkTagItem[] Tags { get; set; } = [];
|
||||
public VoiceWorkCreatorItem[] Creators { get; set; } = [];
|
||||
public string[] SupportedLanguages { get; set; } = [];
|
||||
}
|
||||
|
||||
public class VoiceWorkCircleItem
|
||||
|
||||
@@ -3,6 +3,7 @@ using JSMR.Application.Enums;
|
||||
using JSMR.Application.VoiceWorks.Queries.Search;
|
||||
using JSMR.Domain.Entities;
|
||||
using JSMR.Domain.Enums;
|
||||
using JSMR.Domain.ValueObjects;
|
||||
using JSMR.Infrastructure.Common.Queries;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Linq.Expressions;
|
||||
@@ -60,9 +61,10 @@ public class VoiceWorkSearchProvider(AppDbContext context, IVoiceWorkFullTextSea
|
||||
break;
|
||||
}
|
||||
|
||||
if (criteria.SupportedLanguages.Length > 0)
|
||||
filteredQuery = filteredQuery.Where(x => criteria.SupportedLanguages.AsEnumerable().Contains((Language)x.VoiceWork.SubtitleLanguage));
|
||||
//if (criteria.SupportedLanguages.Length > 0)
|
||||
// filteredQuery = filteredQuery.Where(x => criteria.SupportedLanguages.AsEnumerable().Contains((Language)x.VoiceWork.SubtitleLanguage));
|
||||
|
||||
filteredQuery = ApplySupportedLanguageFilter(filteredQuery, criteria);
|
||||
filteredQuery = ApplyCircleStatusFilter(filteredQuery, criteria);
|
||||
filteredQuery = ApplyTagStatusFilter(filteredQuery, criteria);
|
||||
filteredQuery = ApplyCreatorStatusFilter(filteredQuery, criteria);
|
||||
@@ -118,6 +120,26 @@ public class VoiceWorkSearchProvider(AppDbContext context, IVoiceWorkFullTextSea
|
||||
return query.Where(x => voiceWorkIds.Contains(x.VoiceWork.VoiceWorkId));
|
||||
}
|
||||
|
||||
|
||||
private IQueryable<VoiceWorkQuery> ApplySupportedLanguageFilter(IQueryable<VoiceWorkQuery> query, VoiceWorkSearchCriteria criteria)
|
||||
{
|
||||
if (criteria.SupportedLanguages.Length == 0)
|
||||
return query;
|
||||
|
||||
List<string> languageCodes = [];
|
||||
|
||||
foreach (Language language in criteria.SupportedLanguages)
|
||||
{
|
||||
if (SupportedLanguage.TryFromLanguage(language, out SupportedLanguage? supportedLanguage))
|
||||
languageCodes.Add(supportedLanguage.Code);
|
||||
}
|
||||
|
||||
if (languageCodes.Count == 0)
|
||||
return query;
|
||||
|
||||
return query.Where(q => context.VoiceWorkSupportedLanguages.Any(sl => sl.VoiceWorkId == q.VoiceWork.VoiceWorkId && languageCodes.Contains(sl.Language)));
|
||||
}
|
||||
|
||||
private IQueryable<VoiceWorkQuery> ApplyCircleStatusFilter(IQueryable<VoiceWorkQuery> query, VoiceWorkSearchCriteria criteria)
|
||||
{
|
||||
if (criteria.CircleStatus is null)
|
||||
@@ -432,6 +454,7 @@ public class VoiceWorkSearchProvider(AppDbContext context, IVoiceWorkFullTextSea
|
||||
PlannedReleaseDate = voiceWork.PlannedReleaseDate,
|
||||
Downloads = voiceWork.Downloads,
|
||||
WishlistCount = voiceWork.WishlistCount,
|
||||
Rating = (AgeRating)voiceWork.Rating,
|
||||
Status = voiceWork.Status,
|
||||
SubtitleLanguage = voiceWork.SubtitleLanguage,
|
||||
HasTrial = voiceWork.HasTrial,
|
||||
@@ -449,16 +472,24 @@ public class VoiceWorkSearchProvider(AppDbContext context, IVoiceWorkFullTextSea
|
||||
|
||||
int[] voiceWorkIds = [.. items.Select(i => i.VoiceWorkId)];
|
||||
|
||||
Dictionary<int, VoiceWorkTagItem[]> tagsByVw = await GetTagsAsync(voiceWorkIds, cancellationToken);
|
||||
Dictionary<int, VoiceWorkCreatorItem[]> creatorsByVw = await GetCreatorsAsync(voiceWorkIds, cancellationToken);
|
||||
var tagsByVoiceWork = await GetTagsAsync(voiceWorkIds, cancellationToken);
|
||||
var creatorsByVoiceWork = await GetCreatorsAsync(voiceWorkIds, cancellationToken);
|
||||
var supportedLanguagesByVoiceWork = await GetSupportedLanguagesAsync(voiceWorkIds, cancellationToken);
|
||||
var originalCirclesByVoiceWork = await GetOriginalCircles(voiceWorkIds, cancellationToken);
|
||||
|
||||
foreach (VoiceWorkSearchResult item in items)
|
||||
{
|
||||
if (tagsByVw.TryGetValue(item.VoiceWorkId, out VoiceWorkTagItem[]? tags))
|
||||
if (tagsByVoiceWork.TryGetValue(item.VoiceWorkId, out VoiceWorkTagItem[]? tags))
|
||||
item.Tags = tags;
|
||||
|
||||
if (creatorsByVw.TryGetValue(item.VoiceWorkId, out VoiceWorkCreatorItem[]? creators))
|
||||
if (creatorsByVoiceWork.TryGetValue(item.VoiceWorkId, out VoiceWorkCreatorItem[]? creators))
|
||||
item.Creators = creators;
|
||||
|
||||
if (supportedLanguagesByVoiceWork.TryGetValue(item.VoiceWorkId, out string[]? supportedLanguages))
|
||||
item.SupportedLanguages = supportedLanguages;
|
||||
|
||||
if (originalCirclesByVoiceWork.TryGetValue(item.VoiceWorkId, out VoiceWorkCircleItem? voiceWorkCircleItem))
|
||||
item.OriginalCircle = voiceWorkCircleItem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,4 +530,51 @@ public class VoiceWorkSearchProvider(AppDbContext context, IVoiceWorkFullTextSea
|
||||
g => g.Select(r => new VoiceWorkCreatorItem { CreatorId = r.CreatorId, Name = r.Name, IsFavorite = r.Favorite, IsBlacklisted = r.Blacklisted }).ToArray()
|
||||
);
|
||||
}
|
||||
|
||||
private async Task<Dictionary<int, string[]>> GetSupportedLanguagesAsync(int[] voiceWorkIds, CancellationToken cancellationToken)
|
||||
{
|
||||
var supportedLanguageRows = await (
|
||||
from voiceWorkSupportedLanguage in context.VoiceWorkSupportedLanguages.AsNoTracking()
|
||||
where voiceWorkIds.Contains(voiceWorkSupportedLanguage.VoiceWorkId)
|
||||
select new { voiceWorkSupportedLanguage.VoiceWorkId, voiceWorkSupportedLanguage.Language }
|
||||
).ToListAsync(cancellationToken);
|
||||
|
||||
return supportedLanguageRows
|
||||
.GroupBy(r => r.VoiceWorkId)
|
||||
.ToDictionary(
|
||||
g => g.Key,
|
||||
g => g.Select(r => r.Language).ToArray()
|
||||
);
|
||||
}
|
||||
|
||||
private async Task<Dictionary<int, VoiceWorkCircleItem>> GetOriginalCircles(int[] voiceWorkIds, CancellationToken cancellationToken)
|
||||
{
|
||||
var originalCircleRows = await (
|
||||
from voiceWork in context.VoiceWorks.AsNoTracking()
|
||||
join orignalVoiceWork in context.VoiceWorks.AsNoTracking() on voiceWork.OriginalProductId equals orignalVoiceWork.ProductId
|
||||
join originalCircle in context.Circles.AsNoTracking() on orignalVoiceWork.CircleId equals originalCircle.CircleId
|
||||
where voiceWorkIds.Contains(voiceWork.VoiceWorkId)
|
||||
select new
|
||||
{
|
||||
voiceWork.VoiceWorkId,
|
||||
originalCircle.Name,
|
||||
originalCircle.MakerId,
|
||||
originalCircle.Favorite,
|
||||
originalCircle.Blacklisted
|
||||
}
|
||||
).ToListAsync(cancellationToken);
|
||||
|
||||
return originalCircleRows
|
||||
.GroupBy(r => r.VoiceWorkId)
|
||||
.ToDictionary(
|
||||
g => g.Key,
|
||||
g => g.Select(r => new VoiceWorkCircleItem()
|
||||
{
|
||||
Name = r.Name,
|
||||
MakerId = r.MakerId,
|
||||
IsFavorite = r.Favorite,
|
||||
IsBlacklisted = r.Blacklisted
|
||||
}).First()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,12 @@
|
||||
@if (string.IsNullOrWhiteSpace(Url))
|
||||
{
|
||||
<div class="@GetClasses()" @onclick="@OnClickAsync">
|
||||
@if (Graphic != null)
|
||||
@if (Graphic != null && Graphic != Enums.Graphic.None)
|
||||
{
|
||||
<Icon Graphic="@Graphic.Value"
|
||||
Varient="@(IconVarient ?? Enums.IconVarient.None)"
|
||||
Size="@(IconSize ?? Enums.SizeVarient.Small)"
|
||||
Color="@Color">
|
||||
UseCurrentColor>
|
||||
</Icon>
|
||||
}
|
||||
<span>@ChildContent</span>
|
||||
@@ -23,7 +23,7 @@ else
|
||||
Graphic="@Graphic.Value"
|
||||
Varient="@(IconVarient ?? Enums.IconVarient.None)"
|
||||
Size="@(IconSize ?? Enums.SizeVarient.Small)"
|
||||
Color="@Color">
|
||||
UseCurrentColor>
|
||||
</Icon>
|
||||
}
|
||||
<span>@ChildContent</span>
|
||||
@@ -94,6 +94,11 @@ else
|
||||
break;
|
||||
}
|
||||
|
||||
if (Varient == ElementVarient.Filled && Tone == ToneVarient.Tint)
|
||||
{
|
||||
classNames.Add($"varient-tint");
|
||||
}
|
||||
|
||||
if (Click.HasDelegate || string.IsNullOrWhiteSpace(Url) == false)
|
||||
{
|
||||
classNames.Add("is-clickable");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@using JSMR.UI.Blazor.Enums
|
||||
|
||||
<div class="@GetIconClasses()"></div>
|
||||
<div class="@GetIconClasses()" style="@GetStyle()"></div>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
@@ -15,20 +15,33 @@
|
||||
[Parameter]
|
||||
public ColorVarient Color { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool UseCurrentColor { get; set; }
|
||||
|
||||
private string GetIconClasses()
|
||||
{
|
||||
string graphic = Varient == IconVarient.None
|
||||
? Graphic.ToString().ToLower()
|
||||
: $"{Graphic.ToString().ToLower()}-{Varient.ToString().ToLower()}";
|
||||
|
||||
|
||||
List<string> classNames =
|
||||
[
|
||||
$"j-icon",
|
||||
$"j-icon-{graphic}",
|
||||
$"size-{Size.ToString().ToLower()}",
|
||||
$"background-color-{Color.ToString().ToLower()}"
|
||||
//$"background-color-{Color.ToString().ToLower()}"
|
||||
];
|
||||
|
||||
if (!UseCurrentColor)
|
||||
{
|
||||
classNames.Add($"background-color-{Color.ToString().ToLower()}");
|
||||
}
|
||||
|
||||
return string.Join(" ", classNames);
|
||||
}
|
||||
|
||||
private string? GetStyle()
|
||||
{
|
||||
return UseCurrentColor ? "background-color: currentColor;" : null;
|
||||
}
|
||||
}
|
||||
@@ -15,34 +15,66 @@
|
||||
<div class="j-product-title">
|
||||
<a href="@Product.ProductUrl" target="_blank">@Product.ProductName</a>
|
||||
</div>
|
||||
<div class="j-product-contributors">
|
||||
<span class="j-circle">
|
||||
<MudChip T="string"
|
||||
<BitStack Horizontal="true" Gap="0.5em" AutoHeight Wrap>
|
||||
@* <MudChip T="string"
|
||||
Href=@($"https://www.dlsite.com/maniax/circle/profile/=/maker_id/{Product.MakerId}.html")
|
||||
Target="_blank"
|
||||
Variant="MudBlazor.Variant.Filled"
|
||||
Icon="@Icons.Material.Outlined.Circle">@Product.Maker</MudChip>
|
||||
@* <CircleChip Circle="@Product.Circle"></CircleChip> *@
|
||||
@foreach (var creator in Product.Creators)
|
||||
{
|
||||
<MudChip T="string"
|
||||
Icon="@Icons.Material.Outlined.Circle">@Product.Maker</MudChip> *@
|
||||
@* <CircleChip Circle="@Product.Circle"></CircleChip> *@
|
||||
<Chip Graphic="Graphic.Circle" Varient="ElementVarient.Outlined" Color="ColorVarient.Secondary" Url=@($"https://www.dlsite.com/maniax/circle/profile/=/maker_id/{Product.MakerId}.html")>@Product.Maker</Chip>
|
||||
|
||||
@if (Product.OriginalCircle is not null)
|
||||
{
|
||||
<Chip Graphic="Graphic.Circle" Varient="ElementVarient.Outlined" Color="ColorVarient.Secondary" Url=@($"https://www.dlsite.com/maniax/circle/profile/=/maker_id/{Product.OriginalCircle.MakerId}.html")>@Product.OriginalCircle.Name</Chip>
|
||||
}
|
||||
|
||||
@foreach (var creator in Product.Creators)
|
||||
{
|
||||
@* <MudChip T="string"
|
||||
Href=@($"https://www.dlsite.com/maniax/fsr/=/keyword_creater/{creator.Name}")
|
||||
Target="_blank"
|
||||
Variant="MudBlazor.Variant.Filled"
|
||||
Icon="@Icons.Material.Filled.Person">@creator.Name</MudChip>
|
||||
@* <CreatorChip Creator="@creator"></CreatorChip> *@
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
Icon="@Icons.Material.Filled.Person">@creator.Name</MudChip> *@
|
||||
@* <CreatorChip Creator="@creator"></CreatorChip> *@
|
||||
<Chip Graphic="Graphic.Person" Varient="ElementVarient.Outlined" IconVarient="IconVarient.Fill" Color="ColorVarient.Secondary" Url=@($"https://www.dlsite.com/maniax/fsr/=/keyword_creater/{creator.Name}")>@creator.Name</Chip>
|
||||
}
|
||||
</BitStack>
|
||||
<BitStack Horizontal="true" Gap="0.5em" AutoHeight Wrap>
|
||||
@foreach (string supportedLanguage in Product.SupportedLanguages)
|
||||
{
|
||||
<Chip Graphic="Graphic.Globe" Varient="ElementVarient.Outlined" Color="ColorVarient.Secondary">@GetSupportedLanguageDescription(supportedLanguage)</Chip>
|
||||
}
|
||||
@if (Product.OriginalProductId is not null)
|
||||
{
|
||||
<Chip Graphic="Graphic.Translate" Varient="ElementVarient.Outlined" Color="ColorVarient.Secondary">Translation</Chip>
|
||||
}
|
||||
@if (Product.Rating == AgeRating.AllAges)
|
||||
{
|
||||
<Chip Graphic="Graphic.Age" Color="ColorVarient.Green" Varient="ElementVarient.Outlined">All Ages</Chip>
|
||||
}
|
||||
else if (Product.Rating == AgeRating.R15)
|
||||
{
|
||||
<Chip Graphic="Graphic.Age" Color="ColorVarient.Blue" Varient="ElementVarient.Outlined">R-15</Chip>
|
||||
}
|
||||
@if (Product.HasTrial || Product.HasChobit)
|
||||
{
|
||||
<Chip Graphic="Graphic.Download" Color="ColorVarient.Yellow" Varient="ElementVarient.Outlined">Trial</Chip>
|
||||
}
|
||||
@if (Product.Favorite)
|
||||
{
|
||||
<Chip Graphic="Graphic.Star" Color="ColorVarient.Teal" Varient="ElementVarient.Outlined">Favorite</Chip>
|
||||
}
|
||||
</BitStack>
|
||||
<div class="j-product-description">@Product.Description</div>
|
||||
<div class="j-tags">
|
||||
@foreach (var tag in Product.Tags)
|
||||
{
|
||||
@* <div class="j-tag">@tag.Name</div> *@
|
||||
@* <div class="j-tag">@tag.Name</div> *@
|
||||
<ProductTag Tag="tag"></ProductTag>
|
||||
}
|
||||
</div>
|
||||
@* <div class="j-tags">
|
||||
@* <div class="j-tags">
|
||||
@foreach (var tag in Product.Tags)
|
||||
{
|
||||
<TagChip Tag="tag"></TagChip>
|
||||
@@ -149,4 +181,17 @@
|
||||
return "jp";
|
||||
}
|
||||
}
|
||||
|
||||
private string GetSupportedLanguageDescription(string code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case "JPN": return "Japanese";
|
||||
case "ENG": return "English";
|
||||
case "CHI_HANS": return "Chinese (Simplified)";
|
||||
case "CHI_HANT": return "Chinese (Traditional)";
|
||||
case "KO_KR": return "Korean";
|
||||
default: return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
@using JSMR.Application.Tags.Queries.Search.Contracts
|
||||
@using JSMR.Application.VoiceWorks.Queries.Search
|
||||
@using JSMR.UI.Blazor.Enums
|
||||
@using JSMR.UI.Blazor.Filters
|
||||
@using JSMR.UI.Blazor.Services
|
||||
@using Microsoft.AspNetCore.WebUtilities
|
||||
|
||||
<a class="@Classes" @onclick="@OnClick"><Icon Graphic="Enums.Graphic.Tag" Color="Enums.ColorVarient.Primary"></Icon>@Tag.Name</a>
|
||||
@* <a class="@Classes" @onclick="@OnClick"><Icon Graphic="Enums.Graphic.Tag" Color="Enums.ColorVarient.Primary"></Icon>@Tag.Name</a> *@
|
||||
@* <MudChip T="string" Icon="@Icons.Material.Outlined.Tag" @onclick="@OnClick" Variant="@MudBlazor.Variant.Filled" Color="@MudBlazor.Color.Surface">@Tag.Name</MudChip> *@
|
||||
<Chip Graphic="Graphic.Tag" Varient="ElementVarient.Outlined" Color="@GetColorVarient()" Tone="ToneVarient.None" Click="@OnClick">@Tag.Name</Chip>
|
||||
|
||||
@code {
|
||||
[Inject]
|
||||
@@ -33,6 +35,21 @@
|
||||
return string.Join(" ", classNames);
|
||||
}
|
||||
|
||||
private ColorVarient GetColorVarient()
|
||||
{
|
||||
if (Tag.IsFavorite)
|
||||
{
|
||||
return ColorVarient.Mint;
|
||||
}
|
||||
|
||||
if (Tag.IsFavorite)
|
||||
{
|
||||
return ColorVarient.Orange;
|
||||
}
|
||||
|
||||
return ColorVarient.Primary;
|
||||
}
|
||||
|
||||
private void OnClick()
|
||||
{
|
||||
VoiceWorkFilterState state = new()
|
||||
|
||||
@@ -19,5 +19,7 @@ public enum Graphic
|
||||
Sort,
|
||||
Grid,
|
||||
Age,
|
||||
Calendar
|
||||
Calendar,
|
||||
Download,
|
||||
Microphone
|
||||
}
|
||||
@@ -3,32 +3,42 @@ using JSMR.Application.Creators.Queries.Search;
|
||||
using JSMR.Application.Tags.Queries.Search;
|
||||
using JSMR.Application.VoiceWorks.Queries.Search;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace JSMR.UI.Blazor.Services;
|
||||
|
||||
public class VoiceWorksClient(HttpClient http)
|
||||
{
|
||||
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web)
|
||||
{
|
||||
Converters =
|
||||
{
|
||||
new JsonStringEnumConverter()
|
||||
}
|
||||
};
|
||||
|
||||
public async Task<SearchVoiceWorksResponse?> SearchAsync(SearchVoiceWorksRequest request, CancellationToken ct = default)
|
||||
{
|
||||
using var resp = await http.PostAsJsonAsync("/api/voiceworks/search", request, ct);
|
||||
return await resp.Content.ReadFromJsonAsync<SearchVoiceWorksResponse>(cancellationToken: ct);
|
||||
return await resp.Content.ReadFromJsonAsync<SearchVoiceWorksResponse>(JsonOptions, cancellationToken: ct);
|
||||
}
|
||||
|
||||
public async Task<SearchCirclesResponse?> SearchAsync(SearchCirclesRequest request, CancellationToken ct = default)
|
||||
{
|
||||
using var resp = await http.PostAsJsonAsync("/api/circles/search", request, ct);
|
||||
return await resp.Content.ReadFromJsonAsync<SearchCirclesResponse>(cancellationToken: ct);
|
||||
return await resp.Content.ReadFromJsonAsync<SearchCirclesResponse>(JsonOptions, cancellationToken: ct);
|
||||
}
|
||||
|
||||
public async Task<SearchCreatorsResponse?> SearchAsync(SearchCreatorsRequest request, CancellationToken ct = default)
|
||||
{
|
||||
using var resp = await http.PostAsJsonAsync("/api/creators/search", request, ct);
|
||||
return await resp.Content.ReadFromJsonAsync<SearchCreatorsResponse>(cancellationToken: ct);
|
||||
return await resp.Content.ReadFromJsonAsync<SearchCreatorsResponse>(JsonOptions, cancellationToken: ct);
|
||||
}
|
||||
|
||||
public async Task<SearchTagsResponse?> SearchAsync(SearchTagsRequest request, CancellationToken ct = default)
|
||||
{
|
||||
using var resp = await http.PostAsJsonAsync("/api/tags/search", request, ct);
|
||||
return await resp.Content.ReadFromJsonAsync<SearchTagsResponse>(cancellationToken: ct);
|
||||
return await resp.Content.ReadFromJsonAsync<SearchTagsResponse>(JsonOptions, cancellationToken: ct);
|
||||
}
|
||||
}
|
||||
@@ -592,6 +592,7 @@ code {
|
||||
.j-tags {
|
||||
display: flex;
|
||||
gap: .75rem .5rem;
|
||||
gap: .5rem .5rem;
|
||||
flex-wrap: wrap;
|
||||
/*gap: .5rem 1rem;*/
|
||||
}
|
||||
@@ -647,41 +648,70 @@ code {
|
||||
.j-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: .4rem;
|
||||
gap: .5em;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
font-size: .8rem;
|
||||
font-weight: 400;
|
||||
/*--chip-rgb: var(--secondary-rgb, 148 163 184);
|
||||
--chip-tint-alpha: 0.12;*/
|
||||
|
||||
--chip-rgb: var(--secondary-rgb, 148 163 184);
|
||||
--chip-bg-rgb: transparent;
|
||||
--chip-fg-rgb: var(--chip-rgb);
|
||||
--chip-border-rgb: transparent;
|
||||
--chip-tint-alpha: 0.12;
|
||||
color: rgb(var(--chip-fg-rgb));
|
||||
background: rgb(var(--chip-bg-rgb));
|
||||
border: 1px solid rgb(var(--chip-border-rgb));
|
||||
padding: .5em 1em;
|
||||
border-radius: 1rem;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.j-chip.is-clickable {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
--chip-hover-alpha: 0.2;
|
||||
transition: .2s linear;
|
||||
transition: background .2s linear, color .2s linear, border-color .2s linear, filter .2s linear;
|
||||
}
|
||||
|
||||
.j-chip.is-clickable:hover {
|
||||
background: rgb(var(--chip-rgb) / var(--chip-hover-alpha));
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
.j-chip.varient-filled {
|
||||
padding: .4rem .8rem;
|
||||
border-radius: 1rem;
|
||||
--chip-bg-rgb: var(--chip-rgb);
|
||||
--chip-border-rgb: var(--chip-rgb);
|
||||
}
|
||||
|
||||
/*.j-chip.varient-outlined {
|
||||
--chip-bg-rgb: transparent;
|
||||
--chip-fg-rgb: var(--chip-rgb);
|
||||
--chip-border-rgb: var(--chip-rgb);
|
||||
}*/
|
||||
|
||||
.j-chip.varient-outlined {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
padding: .4rem .8rem;
|
||||
border-radius: 1rem;
|
||||
border-color: rgb(var(--chip-rgb));
|
||||
background: rgba(0,0,0,.35);
|
||||
border: 1px solid rgb(var(--chip-rgb) / 0.65);
|
||||
color: rgb(var(--chip-rgb));
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* .j-chip.varient-tint {
|
||||
--chip-bg-rgb: var(--chip-rgb) / var(--chip-tint-alpha);
|
||||
--chip-fg-rgb: var(--chip-rgb);
|
||||
--chip-border-rgb: transparent;
|
||||
}*/
|
||||
|
||||
.j-chip.varient-tint {
|
||||
--chip-bg-alpha: 0.14;
|
||||
--chip-border-alpha: 0.32;
|
||||
color: rgb(var(--chip-rgb));
|
||||
background: rgb(var(--chip-rgb) / var(--chip-bg-alpha));
|
||||
/*border: 1px solid rgb(var(--chip-rgb) / var(--chip-border-alpha));*/
|
||||
}
|
||||
|
||||
|
||||
/* Old ? */
|
||||
.j-chip.tone-tint {
|
||||
background: rgb(var(--chip-rgb) / var(--chip-tint-alpha));
|
||||
}
|
||||
@@ -698,6 +728,74 @@ code {
|
||||
--chip-rgb: var(--rgb-teal);
|
||||
}
|
||||
|
||||
/* New */
|
||||
.j-chip.color-primary {
|
||||
--chip-rgb: var(--rgb-primary);
|
||||
}
|
||||
|
||||
.j-chip.varient-filled.color-primary {
|
||||
--chip-fg-rgb: var(--rgb-on-primary, 0 0 0);
|
||||
}
|
||||
|
||||
.j-chip.color-secondary {
|
||||
--chip-rgb: var(--rgb-secondary);
|
||||
}
|
||||
|
||||
.j-chip.varient-filled.color-secondary {
|
||||
--chip-fg-rgb: var(--rgb-on-secondary, 0 0 0);
|
||||
}
|
||||
|
||||
.j-chip.color-mint {
|
||||
--chip-rgb: var(--rgb-mint);
|
||||
}
|
||||
|
||||
.j-chip.varient-filled.color-mint {
|
||||
--chip-fg-rgb: var(--rgb-on-mint, 0 0 0);
|
||||
}
|
||||
|
||||
.j-chip.color-green {
|
||||
--chip-rgb: var(--rgb-green);
|
||||
}
|
||||
|
||||
.j-chip.varient-filled.color-green {
|
||||
--chip-fg-rgb: var(--rgb-on-green, 255 255 255);
|
||||
}
|
||||
|
||||
.j-chip.color-yellow {
|
||||
color: rgb(var(--chip-fg-rgb));
|
||||
--chip-rgb: var(--rgb-yellow);
|
||||
}
|
||||
|
||||
.j-chip.varient-filled.color-yellow {
|
||||
--chip-fg-rgb: var(--rgb-on-yellow, 255 255 255);
|
||||
}
|
||||
|
||||
.j-chip.color-pink {
|
||||
color: rgb(var(--chip-fg-rgb));
|
||||
--chip-rgb: var(--rgb-pink);
|
||||
}
|
||||
|
||||
.j-chip.varient-filled.color-pink {
|
||||
--chip-fg-rgb: var(--rgb-on-pink, 255 255 255);
|
||||
}
|
||||
|
||||
.j-chip.color-teal {
|
||||
--chip-rgb: var(--rgb-teal);
|
||||
}
|
||||
|
||||
.j-chip.varient-filled.color-teal {
|
||||
--chip-fg-rgb: var(--rgb-on-teal, 255 255 255);
|
||||
}
|
||||
|
||||
.j-chip.color-black {
|
||||
color: inherit;
|
||||
--chip-rgb: 39 39 39;
|
||||
}
|
||||
|
||||
.j-chip.varient-filled.color-black {
|
||||
--chip-fg-rgb: var(--primary-text-color);
|
||||
}
|
||||
|
||||
/* Icons */
|
||||
.j-icon {
|
||||
mask-repeat: no-repeat;
|
||||
@@ -825,6 +923,22 @@ code {
|
||||
mask-image: url("../svg/age-rating.svg");
|
||||
}
|
||||
|
||||
.j-icon-download {
|
||||
mask-image: url("../svg/cloud-download.svg");
|
||||
}
|
||||
|
||||
.j-icon-download-fill {
|
||||
mask-image: url("../svg/cloud-download-fill.svg");
|
||||
}
|
||||
|
||||
.j-icon-microphone {
|
||||
mask-image: url("../svg/microphone.svg");
|
||||
}
|
||||
|
||||
.j-icon-microphone-fill {
|
||||
mask-image: url("../svg/microphone-fill.svg");
|
||||
}
|
||||
|
||||
.j-icon-2 {
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
--input-focus-border-color: #64b5f6;
|
||||
--input-focus-box-shadow: 0 0 0 1px #93cbf9;
|
||||
/* RGB Tokens */
|
||||
--rgb-primary: 180 200 214;
|
||||
--rgb-secondary: 200 220 234;
|
||||
--rgb-mint: 167 243 208;
|
||||
--rgb-green: 175 224 125;
|
||||
--rgb-teal: 110 236 255;
|
||||
--rgb-yellow: 255 224 115;
|
||||
--rgb-on-yellow: 0 0 0;
|
||||
--rgb-pink: 224 104 148;
|
||||
--rgb-on-pink: 255 255 255;
|
||||
/* Colors */
|
||||
--color-primary: rgb(180,200, 214);
|
||||
--color-secondary: rgb(200,220,234);
|
||||
|
||||
3
JSMR.UI.Blazor/wwwroot/svg/cloud-download-fill.svg
Normal file
3
JSMR.UI.Blazor/wwwroot/svg/cloud-download-fill.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-cloud-download-fill" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M8 0a5.53 5.53 0 0 0-3.594 1.342c-.766.66-1.321 1.52-1.464 2.383C1.266 4.095 0 5.555 0 7.318 0 9.366 1.708 11 3.781 11H7.5V5.5a.5.5 0 0 1 1 0V11h4.188C14.502 11 16 9.57 16 7.773c0-1.636-1.242-2.969-2.834-3.194C12.923 1.999 10.69 0 8 0m-.354 15.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 14.293V11h-1v3.293l-2.146-2.147a.5.5 0 0 0-.708.708z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 525 B |
4
JSMR.UI.Blazor/wwwroot/svg/cloud-download.svg
Normal file
4
JSMR.UI.Blazor/wwwroot/svg/cloud-download.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-cloud-download" viewBox="0 0 16 16">
|
||||
<path d="M4.406 1.342A5.53 5.53 0 0 1 8 0c2.69 0 4.923 2 5.166 4.579C14.758 4.804 16 6.137 16 7.773 16 9.569 14.502 11 12.687 11H10a.5.5 0 0 1 0-1h2.688C13.979 10 15 8.988 15 7.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 2.825 10.328 1 8 1a4.53 4.53 0 0 0-2.941 1.1c-.757.652-1.153 1.438-1.153 2.055v.448l-.445.049C2.064 4.805 1 5.952 1 7.318 1 8.785 2.23 10 3.781 10H6a.5.5 0 0 1 0 1H3.781C1.708 11 0 9.366 0 7.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383"/>
|
||||
<path d="M7.646 15.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 14.293V5.5a.5.5 0 0 0-1 0v8.793l-2.146-2.147a.5.5 0 0 0-.708.708z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 768 B |
4
JSMR.UI.Blazor/wwwroot/svg/microphone-fill.svg
Normal file
4
JSMR.UI.Blazor/wwwroot/svg/microphone-fill.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-mic-fill" viewBox="0 0 16 16">
|
||||
<path d="M5 3a3 3 0 0 1 6 0v5a3 3 0 0 1-6 0z"/>
|
||||
<path d="M3.5 6.5A.5.5 0 0 1 4 7v1a4 4 0 0 0 8 0V7a.5.5 0 0 1 1 0v1a5 5 0 0 1-4.5 4.975V15h3a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1h3v-2.025A5 5 0 0 1 3 8V7a.5.5 0 0 1 .5-.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 354 B |
4
JSMR.UI.Blazor/wwwroot/svg/microphone.svg
Normal file
4
JSMR.UI.Blazor/wwwroot/svg/microphone.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-mic" viewBox="0 0 16 16">
|
||||
<path d="M3.5 6.5A.5.5 0 0 1 4 7v1a4 4 0 0 0 8 0V7a.5.5 0 0 1 1 0v1a5 5 0 0 1-4.5 4.975V15h3a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1h3v-2.025A5 5 0 0 1 3 8V7a.5.5 0 0 1 .5-.5"/>
|
||||
<path d="M10 8a2 2 0 1 1-4 0V3a2 2 0 1 1 4 0zM8 0a3 3 0 0 0-3 3v5a3 3 0 0 0 6 0V3a3 3 0 0 0-3-3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 400 B |
Reference in New Issue
Block a user