Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DevToys 2.0] Added CheckBox and ToggleSwitch #841

Merged
merged 11 commits into from
Jun 8, 2023
79 changes: 79 additions & 0 deletions src/app/dev/DevToys.Blazor/Assets/sass/theme/windows/dark.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,19 @@
--control-fill-color-transparent: rgba(255, 255, 255, 0);
--control-fill-color-input-active: rgba(30, 30, 30, 0.702);

--control-alt-fill-color-transparent: rgba(255, 255, 255, 0);
--control-alt-fill-color-secondary: rgba(0, 0, 0, 0.098);
--control-alt-fill-color-tertiary: rgba(255, 255, 255, 0.043);
--control-alt-fill-color-quarternary: rgba(255, 255, 255, 0.071);
--control-alt-fill-color-disabled: rgba(255, 255, 255, 0);

/* Control Stroke */
--control-stroke-color-default: rgba(255, 255, 255, 0.071);
--control-stroke-color-secondary: rgba(255, 255, 255, 0.094);
--control-stroke-on-accent-default: hsla(0, 0%, 100%, 8%);
--control-stroke-on-accent-secondary: hsla(0, 0%, 0%, 14%);
--control-strong-stroke-default: rgba(255, 255, 255, 0.544);
--control-strong-stroke-disabled: rgba(255, 255, 255, 0.157);

/* Subtle Fill */
--subtle-fill-transparent: transparent;
Expand Down Expand Up @@ -114,6 +121,78 @@
--stealth-button-border-disabled: var(--control-fill-color-transparent);
--stealth-button-border-thickness: 1px solid;

/* CheckBox */
--check-box-check-corner-radius: var(--control-corner-radius);
--check-box-foreground: var(--text-fill-color-primary);
--check-box-foreground-disabled: var(--text-fill-color-disabled);

--check-box-check-background-stroke-unchecked: var(--control-strong-stroke-default);
--check-box-check-background-stroke-unchecked-pointer-over: var(--control-strong-stroke-default);
--check-box-check-background-stroke-unchecked-pressed: var(--control-strong-stroke-disabled);
--check-box-check-background-stroke-unchecked-disabled: var(--control-strong-stroke-disabled);

--check-box-check-background-stroke-checked: var(--accent-default);
--check-box-check-background-stroke-checked-pointer-over: var(--accent-secondary);
--check-box-check-background-stroke-checked-pressed: var(--accent-tertiary);
--check-box-check-background-stroke-checked-disabled: var(--control-strong-stroke-disabled);

--check-box-check-background-fill-unchecked: var(--control-alt-fill-color-secondary);
--check-box-check-background-fill-unchecked-pointer-over: var(--control-alt-fill-color-tertiary);
--check-box-check-background-fill-unchecked-pressed: var(--control-alt-fill-color-quarternary);
--check-box-check-background-fill-unchecked-disabled: var(--control-alt-fill-color-disabled);

--check-box-check-background-fill-checked: var(--accent-default);
--check-box-check-background-fill-checked-pointer-over: var(--accent-secondary);
--check-box-check-background-fill-checked-pressed: var(--accent-tertiary);
--check-box-check-background-fill-checked-disabled: var(--accent-disabled);

--check-box-check-glyph-foreground-unchecked: var(--text-on-accent-primary);
--check-box-check-glyph-foreground-unchecked-pointer-over: var(--text-on-accent-primary);
--check-box-check-glyph-foreground-unchecked-pressed: var(--text-on-accent-primary);
--check-box-check-glyph-foreground-unchecked-disabled: var(--text-on-accent-disabled);

--check-box-check-glyph-foreground-checked: var(--text-on-accent-primary);
--check-box-check-glyph-foreground-checked-pointer-over: var(--text-on-accent-primary);
--check-box-check-glyph-foreground-checked-pressed: var(--text-on-accent-secondary);
--check-box-check-glyph-foreground-checked-disabled: var(--text-on-accent-disabled);

/* ToggleSwitch */
--toggle-switch-foreground: var(--text-fill-color-primary);
--toggle-switch-foreground-disabled: var(--text-fill-color-disabled);
--toggle-switch-on-stroke-thickness: 0px;
--toggle-switch-outer-border-stroke-thickness: 1px;

--toggle-switch-fill-off: var(--control-alt-fill-color-secondary);
--toggle-switch-fill-off-pointer-over: var(--control-alt-fill-color-tertiary);
--toggle-switch-fill-off-pressed: var(--control-alt-fill-color-quarternary);
--toggle-switch-fill-off-disabled: var(--control-alt-fill-color-disabled);

--toggle-switch-stroke-off: var(--control-strong-stroke-default);
--toggle-switch-stroke-off-pointer-over: var(--control-strong-stroke-default);
--toggle-switch-stroke-off-pressed: var(--control-strong-stroke-default);
--toggle-switch-stroke-off-disabled: var(--control-strong-stroke-disabled);

--toggle-switch-fill-on: var(--accent-default);
--toggle-switch-fill-on-pointer-over: var(--accent-secondary);
--toggle-switch-fill-on-pressed: var(--accent-tertiary);
--toggle-switch-fill-on-disabled: var(--accent-disabled);

--toggle-switch-stroke-on: var(--accent-default);
--toggle-switch-stroke-on-pointer-over: var(--accent-secondary);
--toggle-switch-stroke-on-pressed: var(--accent-tertiary);
--toggle-switch-stroke-on-disabled: var(--accent-disabled);

--toggle-switch-knob-fill-off: var(--text-fill-color-secondary);
--toggle-switch-knob-fill-off-pointer-over: var(--text-fill-color-secondary);
--toggle-switch-knob-fill-off-pressed: var(--text-fill-color-secondary);
--toggle-switch-knob-fill-off-disabled: var(--text-fill-color-disabled);

--toggle-switch-knob-fill-on: var(--text-on-accent-primary);
--toggle-switch-knob-fill-on-pointer-over: var(--text-on-accent-primary);
--toggle-switch-knob-fill-on-pressed: var(--text-on-accent-primary);
--toggle-switch-knob-fill-on-disabled: var(--text-on-accent-disabled);
--toggle-switch-knob-stroke-on: var(--control-border-color-default);

/* GridView */
--grid-view-header-border-line: rgba(255, 255, 255, 0.2);
--grid-view-item-background: var(--card-background-color);
Expand Down
1 change: 1 addition & 0 deletions src/app/dev/DevToys.Blazor/Components/Button/Button.razor
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
role="button"
class="@(FinalCssClasses)"
style="@(Style)"
tabindex="0"
@ref=Element
@attributes="AdditionalAttributes">
@ChildContent
Expand Down
34 changes: 34 additions & 0 deletions src/app/dev/DevToys.Blazor/Components/CheckBox/CheckBox.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
@namespace DevToys.Blazor.Components

@inherits JSStyledComponentBase

<CascadingValue Value="this" IsFixed="true">
<label
id=@Id
role="button"
class="checkbox-container @(IsEnabled ? string.Empty : "disabled")"
style="@(Style)"
@ref=Element>
<span class="checkbox-inner">
<input
type="checkbox"
tabindex="0"
class="checkbox @(FinalCssClasses)"
checked="@IsChecked"
disabled="@(!IsEnabled)"
@onclick:preventDefault="@(!IsEnabled)"
@onchange="OnChange"
@attributes="AdditionalAttributes" />
<svg
aria-hidden="true"
class="checkbox-glyph"
viewBox="0 0 24 24">
<path
class="path-checkmark"
d="M 4.5303 12.9697 L 8.5 16.9393 L 18.9697 6.4697"
fill="none" />
</svg>
</span>
<TextBlock Text="@Text" />
</label>
</CascadingValue>
37 changes: 37 additions & 0 deletions src/app/dev/DevToys.Blazor/Components/CheckBox/CheckBox.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
namespace DevToys.Blazor.Components;

public partial class CheckBox : JSStyledComponentBase
{
/// <summary>
/// Gets or sets the text to display in the check box.
/// </summary>
[Parameter]
public string? Text { get; set; }

/// <summary>
/// Gets or sets whether the check box is checked.
/// </summary>
[Parameter]
public bool IsChecked { get; set; }

/// <summary>
/// Raised when the check box is toggled.
/// </summary>
[Parameter]
public EventCallback<bool> OnCheckedChanged { get; set; }

internal ValueTask<bool> FocusAsync()
{
return JSRuntime.InvokeVoidWithErrorHandlingAsync("devtoys.DOM.setFocus", Element);
}

private void OnChange(ChangeEventArgs ev)
{
bool value = (ev.Value as bool?) ?? false;
if (value != IsChecked)
{
IsChecked = value;
OnCheckedChanged.InvokeAsync(value);
}
}
}
125 changes: 125 additions & 0 deletions src/app/dev/DevToys.Blazor/Components/CheckBox/CheckBox.razor.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
@use "../../Assets/sass/devtoys" as *;

.checkbox {
@include typography-body;
margin: 0;
border: 1px solid var(--check-box-check-background-stroke-unchecked);
border-radius: var(--check-box-check-corner-radius);
outline: none;
background-clip: padding-box;
background-color: var(--check-box-check-background-fill-unchecked);
color: var(--check-box-check-glyph-foreground-unchecked);
appearance: none;
inline-size: 20px;
block-size: 20px;

&:focus-visible {
box-shadow: var(--focus-stroke);
}

&:hover {
background-color: var(--check-box-check-background-fill-unchecked-pointer-over);
border-color: var(--check-box-check-background-stroke-unchecked-pointer-over);
color: var(--check-box-check-glyph-foreground-unchecked-pointer-over);
}

&:active {
border-color: var(--check-box-check-background-stroke-unchecked-pressed);
background-color: var(--check-box-check-background-fill-unchecked-pressed);
color: var(--check-box-check-glyph-foreground-unchecked-pressed);

+.checkbox-glyph {
color: var(--text-on-accent-secondary);
}
}

&:disabled {
border-color: var(--check-box-check-background-stroke-unchecked-disabled);
background-color: var(--check-box-check-background-fill-unchecked-disabled);
color: var(--check-box-check-glyph-foreground-unchecked-disabled);
pointer-events: none;
}

&:checked {
border: none;
border-color: var(--check-box-check-background-stroke-checked);
background-color: var(--check-box-check-background-fill-checked);
color: var(--check-box-check-glyph-foreground-checked);

&:hover {
border-color: var(--check-box-check-background-stroke-checked-pointer-over);
background-color: var(--check-box-check-background-fill-checked-pointer-over);
color: var(--check-box-check-glyph-foreground-checked-pointer-over);
}

&:active {
border-color: var(--check-box-check-background-stroke-checked-pressed);
background-color: var(--check-box-check-background-fill-checked-pressed);
color: var(--check-box-check-glyph-foreground-checked-pressed);
}

&:disabled {
border-color: var(--check-box-check-background-stroke-checked-disabled);
background-color: var(--check-box-check-background-fill-checked-disabled);
color: var(--check-box-check-glyph-foreground-checked-disabled);

+.checkbox-glyph {
color: var(--text-on-accent-disabled);
}
}

+.checkbox-glyph .path-checkmark {
transition: 250ms cubic-bezier(0.55, 0, 0, 1) stroke-dashoffset;
stroke-dashoffset: 0;
}
}

&-container {
@include flex($inline: true, $align: center);
@include typography-body;

color: var(--check-box-foreground) !important;
user-select: none;
min-block-size: 32px;

>span {
padding-inline-start: 8px;
}

&.disabled {
color: var(--check-box-foreground-disabled) !important;
}
}

&-inner {
@include flex($align: center, $justify: center);
position: relative;
}

&-glyph {
pointer-events: none;
position: absolute;
color: var(--check-box-check-glyph-foreground-unchecked);
inline-size: 12px;
block-size: 12px;

path {
transform-origin: center;
}

.path- {
&checkmark {
transform: scale(1.2);
stroke: currentColor;

stroke: {
width: 2;
linecap: round;
linejoin: round;
dasharray: 20.5;
dashoffset: 20.5;
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@namespace DevToys.Blazor.Components

@inherits JSStyledComponentBase

<CascadingValue Value="this" IsFixed="true">
<label
id=@Id
role="button"
class="toggle-switch-container @(IsEnabled ? string.Empty : "disabled")"
style="@(Style)"
@ref=Element>
<input
type="checkbox"
tabindex="0"
class="toggle-switch @(FinalCssClasses)"
checked="@IsOn"
disabled="@(!IsEnabled)"
@onclick:preventDefault="@(!IsEnabled)"
@onchange="OnChange"
@attributes="AdditionalAttributes" />
<TextBlock Text="@Text" />
</label>
</CascadingValue>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
namespace DevToys.Blazor.Components;

public partial class ToggleSwitch : JSStyledComponentBase
{
/// <summary>
/// Gets or sets the text to display in the toggle switch.
/// </summary>
[Parameter]
public string? Text { get; set; }

/// <summary>
/// Gets or sets whether the toggle switch is on.
/// </summary>
[Parameter]
public bool IsOn { get; set; }

/// <summary>
/// Raised when the toggle switch is toggled.
/// </summary>
[Parameter]
public EventCallback<bool> OnCheckedChanged { get; set; }

internal ValueTask<bool> FocusAsync()
{
return JSRuntime.InvokeVoidWithErrorHandlingAsync("devtoys.DOM.setFocus", Element);
}

private void OnChange(ChangeEventArgs ev)
{
bool value = (ev.Value as bool?) ?? false;
if (value != IsOn)
{
IsOn = value;
OnCheckedChanged.InvokeAsync(value);
}
}
}
Loading