mirror of
https://github.com/penpot/penpot.git
synced 2026-04-29 05:08:08 +00:00
💄 Remove css nesting
This commit is contained in:
parent
cad9d03ca1
commit
b4c6bbb191
@ -87,11 +87,11 @@
|
||||
:aria-disabled disabled
|
||||
:aria-label effective-aria-label
|
||||
:class (stl/css-case :switcher true
|
||||
:is-checked current-checked
|
||||
:is-disabled disabled
|
||||
:switcher--sm (= size "sm")
|
||||
:switcher--md (= size "md")
|
||||
:switcher--lg (= size "lg"))
|
||||
:switcher-checked current-checked
|
||||
:switcher-disabled disabled
|
||||
:switcher-sm (= size "sm")
|
||||
:switcher-md (= size "md")
|
||||
:switcher-lg (= size "lg"))
|
||||
:on-click handle-toggle
|
||||
:on-key-down handle-keydown})]
|
||||
|
||||
@ -99,13 +99,11 @@
|
||||
(when has-label
|
||||
[:label {:for id
|
||||
:class (stl/css-case :switcher-label true
|
||||
:is-disabled disabled)
|
||||
:switcher-label-disabled disabled)
|
||||
:on-click handle-label-click}
|
||||
label])
|
||||
[:> :div props
|
||||
[:div {:class (stl/css-case :switcher-track true
|
||||
:is-checked current-checked
|
||||
:is-disabled disabled)}
|
||||
:switcher-track-disabled disabled)}
|
||||
[:div {:class (stl/css-case :switcher-thumb true
|
||||
:is-checked current-checked
|
||||
:is-disabled disabled)}]]]]))
|
||||
:switcher-thumb-disabled disabled)}]]]]))
|
||||
|
||||
@ -24,36 +24,42 @@ $switcher-lg-thumb-size: $sz-24;
|
||||
$switcher-transition-duration: 0.2s;
|
||||
|
||||
.switcher-wrapper {
|
||||
--switcher-track-outline: none;
|
||||
--switcher-track-outline-offset: 0;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--sp-s);
|
||||
padding: 0;
|
||||
|
||||
// Focus ring using DS tokens - on wrapper cascading to track
|
||||
&:focus-visible {
|
||||
.switcher-track {
|
||||
outline: $b-2 solid var(--color-accent-primary);
|
||||
outline-offset: $b-2;
|
||||
}
|
||||
--switcher-track-outline: $b-2 solid var(--color-accent-primary);
|
||||
--switcher-track-outline-offset: #{$b-2};
|
||||
}
|
||||
}
|
||||
|
||||
.switcher-label {
|
||||
color: var(--color-foreground-primary);
|
||||
--switcher-label-color: var(--color-foreground-secondary);
|
||||
|
||||
color: var(--switcher-label-color);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
color: var(--color-foreground-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.switcher-label.is-disabled {
|
||||
.switcher-label-disabled {
|
||||
cursor: not-allowed;
|
||||
color: var(--color-foreground-secondary);
|
||||
}
|
||||
|
||||
.switcher {
|
||||
--switcher-track-width: #{$switcher-md-track-width};
|
||||
--switcher-track-height: #{$switcher-md-track-height};
|
||||
--switcher-thumb-size: #{$switcher-md-thumb-size};
|
||||
--switcher-thumb-transform: translateX(0);
|
||||
--switcher-track-bg: var(--color-background-quaternary);
|
||||
--switcher-thumb-bg: var(--color-foreground-secondary);
|
||||
--switcher-thumb-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06);
|
||||
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
@ -62,131 +68,102 @@ $switcher-transition-duration: 0.2s;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
|
||||
|
||||
|
||||
// Size variants - Medium (default)
|
||||
&.switcher--md {
|
||||
.switcher-track {
|
||||
width: $switcher-md-track-width;
|
||||
height: $switcher-md-track-height;
|
||||
}
|
||||
|
||||
.switcher-thumb {
|
||||
width: $switcher-md-thumb-size;
|
||||
height: $switcher-md-thumb-size;
|
||||
top: calc((#{$switcher-md-track-height} - #{$switcher-md-thumb-size}) / 2);
|
||||
left: calc((#{$switcher-md-track-height} - #{$switcher-md-thumb-size}) / 2);
|
||||
}
|
||||
|
||||
&.is-checked .switcher-thumb {
|
||||
transform: translateX(calc(#{$switcher-md-track-width} - #{$switcher-md-track-height}));
|
||||
}
|
||||
&:hover:not(.switcher-disabled) {
|
||||
--switcher-thumb-bg: var(--color-foreground-primary);
|
||||
}
|
||||
}
|
||||
|
||||
// Size variants - Small
|
||||
.switcher-sm {
|
||||
--switcher-track-width: #{$switcher-sm-track-width};
|
||||
--switcher-track-height: #{$switcher-sm-track-height};
|
||||
--switcher-thumb-size: #{$switcher-sm-thumb-size};
|
||||
}
|
||||
|
||||
// Size variants - Medium (default)
|
||||
.switcher-md {
|
||||
--switcher-track-width: #{$switcher-md-track-width};
|
||||
--switcher-track-height: #{$switcher-md-track-height};
|
||||
--switcher-thumb-size: #{$switcher-md-thumb-size};
|
||||
}
|
||||
|
||||
// Size variants - Large
|
||||
.switcher-lg {
|
||||
--switcher-track-width: #{$switcher-lg-track-width};
|
||||
--switcher-track-height: #{$switcher-lg-track-height};
|
||||
--switcher-thumb-size: #{$switcher-lg-thumb-size};
|
||||
}
|
||||
|
||||
// Checked state
|
||||
.switcher-checked {
|
||||
--switcher-track-bg: var(--color-accent-success);
|
||||
--switcher-thumb-bg: var(--color-foreground-primary);
|
||||
--switcher-thumb-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);
|
||||
|
||||
// Size variants - Small
|
||||
&.switcher--sm {
|
||||
.switcher-track {
|
||||
width: $switcher-sm-track-width;
|
||||
height: $switcher-sm-track-height;
|
||||
}
|
||||
|
||||
.switcher-thumb {
|
||||
width: $switcher-sm-thumb-size;
|
||||
height: $switcher-sm-thumb-size;
|
||||
top: calc((#{$switcher-sm-track-height} - #{$switcher-sm-thumb-size}) / 2);
|
||||
left: calc((#{$switcher-sm-track-height} - #{$switcher-sm-thumb-size}) / 2);
|
||||
}
|
||||
|
||||
&.is-checked .switcher-thumb {
|
||||
transform: translateX(calc(#{$switcher-sm-track-width} - #{$switcher-sm-track-height}));
|
||||
}
|
||||
&:hover:not(.switcher-disabled) {
|
||||
--switcher-track-bg: var(--color-accent-tertiary);
|
||||
}
|
||||
}
|
||||
|
||||
.switcher-checked.switcher-sm {
|
||||
--switcher-thumb-transform: translateX(calc(#{$switcher-sm-track-width} - #{$switcher-sm-track-height}));
|
||||
}
|
||||
|
||||
.switcher-checked.switcher-md {
|
||||
--switcher-thumb-transform: translateX(calc(#{$switcher-md-track-width} - #{$switcher-md-track-height}));
|
||||
}
|
||||
|
||||
.switcher-checked.switcher-lg {
|
||||
--switcher-thumb-transform: translateX(calc(#{$switcher-lg-track-width} - #{$switcher-lg-track-height}));
|
||||
}
|
||||
|
||||
// Disabled state
|
||||
.switcher-disabled {
|
||||
cursor: not-allowed;
|
||||
|
||||
// Size variants - Large
|
||||
&.switcher--lg {
|
||||
.switcher-track {
|
||||
width: $switcher-lg-track-width;
|
||||
height: $switcher-lg-track-height;
|
||||
}
|
||||
|
||||
.switcher-thumb {
|
||||
width: $switcher-lg-thumb-size;
|
||||
height: $switcher-lg-thumb-size;
|
||||
top: calc((#{$switcher-lg-track-height} - #{$switcher-lg-thumb-size}) / 2);
|
||||
left: calc((#{$switcher-lg-track-height} - #{$switcher-lg-thumb-size}) / 2);
|
||||
}
|
||||
|
||||
&.is-checked .switcher-thumb {
|
||||
transform: translateX(calc(#{$switcher-lg-track-width} - #{$switcher-lg-track-height}));
|
||||
}
|
||||
&:not(.switcher-checked) {
|
||||
--switcher-track-bg: var(--color-background-tertiary);
|
||||
--switcher-thumb-bg: var(--color-foreground-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
.switcher-disabled.switcher-checked {
|
||||
--switcher-track-bg: var(--color-background-quaternary);
|
||||
--switcher-thumb-bg: var(--color-foreground-secondary);
|
||||
}
|
||||
|
||||
.switcher-track {
|
||||
position: relative;
|
||||
border-radius: $br-full;
|
||||
background-color: var(--color-background-quaternary);
|
||||
width: var(--switcher-track-width);
|
||||
height: var(--switcher-track-height);
|
||||
border-radius: $br-full;
|
||||
background-color: var(--switcher-track-bg);
|
||||
transition: background-color $switcher-transition-duration ease-in-out;
|
||||
|
||||
.switcher.is-checked & {
|
||||
background-color: var(--color-accent-success);
|
||||
}
|
||||
|
||||
.switcher:not(.is-disabled):hover:not(.is-checked) & {
|
||||
background-color: var(--color-background-quaternary);
|
||||
}
|
||||
|
||||
.switcher:not(.is-disabled):hover.is-checked & {
|
||||
background-color: var(--color-accent-tertiary);
|
||||
}
|
||||
outline: var(--switcher-track-outline);
|
||||
outline-offset: var(--switcher-track-outline-offset);
|
||||
}
|
||||
|
||||
.switcher-track-disabled {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.switcher-thumb {
|
||||
position: absolute;
|
||||
width: var(--switcher-thumb-size);
|
||||
height: var(--switcher-thumb-size);
|
||||
top: calc((var(--switcher-track-height) - var(--switcher-thumb-size)) / 2);
|
||||
left: calc((var(--switcher-track-height) - var(--switcher-thumb-size)) / 2);
|
||||
border-radius: 50%;
|
||||
background-color: var(--color-foreground-secondary);
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06);
|
||||
background-color: var(--switcher-thumb-bg);
|
||||
box-shadow: var(--switcher-thumb-shadow);
|
||||
transform: var(--switcher-thumb-transform);
|
||||
transition: transform $switcher-transition-duration ease-in-out, background-color $switcher-transition-duration ease-in-out;
|
||||
|
||||
.switcher.is-checked & {
|
||||
background-color: var(--color-foreground-primary);
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.switcher:not(.is-disabled):hover:not(.is-checked) & {
|
||||
background-color: var(--color-foreground-primary);
|
||||
}
|
||||
|
||||
.switcher:not(.is-disabled):hover.is-checked & {
|
||||
background-color: var(--color-foreground-primary);
|
||||
}
|
||||
}
|
||||
|
||||
// Flat modifier-based selectors for states
|
||||
.switcher.is-disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.switcher-track.is-disabled {
|
||||
background-color: var(--color-background-tertiary);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.switcher-track.is-disabled.is-checked {
|
||||
background-color: var(--color-background-quaternary);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.switcher-thumb.is-disabled {
|
||||
background-color: var(--color-foreground-secondary);
|
||||
.switcher-thumb-disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.switcher-thumb.is-disabled.is-checked {
|
||||
background-color: var(--color-foreground-secondary);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.switcher-track,
|
||||
.switcher-thumb {
|
||||
|
||||
@ -13,10 +13,6 @@ export default {
|
||||
title: "Controls/Switcher",
|
||||
component: Switcher,
|
||||
argTypes: {
|
||||
checked: {
|
||||
control: { type: "boolean" },
|
||||
description: "Controlled checked state",
|
||||
},
|
||||
defaultChecked: {
|
||||
control: { type: "boolean" },
|
||||
description: "Default checked state for uncontrolled mode",
|
||||
@ -33,15 +29,7 @@ export default {
|
||||
options: ["sm", "md", "lg"],
|
||||
control: { type: "select" },
|
||||
description: "Size variant of the switcher",
|
||||
},
|
||||
"aria-label": {
|
||||
control: { type: "text" },
|
||||
description: "Accessible label when no visible label is provided",
|
||||
},
|
||||
onChange: {
|
||||
action: "changed",
|
||||
description: "Callback fired when the switcher state changes",
|
||||
},
|
||||
}
|
||||
},
|
||||
args: {
|
||||
disabled: false,
|
||||
@ -100,7 +88,6 @@ export const WithLongLabel = {
|
||||
|
||||
export const WithoutVisibleLabel = {
|
||||
args: {
|
||||
"aria-label": "Toggle dark mode",
|
||||
defaultChecked: false,
|
||||
},
|
||||
render: ({ ...args }) => (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user