mirror of
https://github.com/logto-io/logto.git
synced 2025-01-20 21:32:31 -05:00
refactor(console): support icon in radio item (#3077)
This commit is contained in:
parent
2a0ec7f78c
commit
7b9712db9a
3 changed files with 260 additions and 191 deletions
254
packages/console/src/components/RadioGroup/Radio.module.scss
Normal file
254
packages/console/src/components/RadioGroup/Radio.module.scss
Normal file
|
@ -0,0 +1,254 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
// Default Styles
|
||||
.radio {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
font: var(--font-body-2);
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: _.unit(2);
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.indicator {
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--color-neutral-60);
|
||||
display: inline-block;
|
||||
margin-right: _.unit(2);
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
background: var(--color-layer-1);
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--color-layer-1);
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-right: _.unit(2);
|
||||
color: var(--color-text-secondary);
|
||||
|
||||
> svg {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: _.unit(3);
|
||||
border-radius: _.unit(4);
|
||||
border: 1px solid transparent;
|
||||
outline: 1px solid var(--color-neutral-90);
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: unset;
|
||||
}
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
display: block;
|
||||
|
||||
.indicator {
|
||||
border-radius: unset;
|
||||
border: unset;
|
||||
display: block;
|
||||
margin-right: unset;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
|
||||
svg {
|
||||
opacity: 0%;
|
||||
}
|
||||
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-right: _.unit(2);
|
||||
vertical-align: middle;
|
||||
color: var(--color-text-secondary);
|
||||
|
||||
> svg {
|
||||
display: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.disabledLabel {
|
||||
background: var(--color-neutral-90);
|
||||
padding: _.unit(0.5) _.unit(2);
|
||||
border-radius: 10px;
|
||||
font: var(--font-label-3);
|
||||
color: var(--color-text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.compact {
|
||||
position: relative;
|
||||
border: 1px solid var(--color-border);
|
||||
flex: 1;
|
||||
font: var(--font-label-2);
|
||||
|
||||
&:first-child {
|
||||
border-radius: 12px 0 0 12px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-radius: 0 12px 12px 0;
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: unset;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: _.unit(5);
|
||||
|
||||
.icon {
|
||||
margin-right: _.unit(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Checked Styles
|
||||
.radio.checked {
|
||||
.content {
|
||||
.indicator {
|
||||
border-color: var(--color-primary);
|
||||
|
||||
&::before {
|
||||
background: var(--color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card.checked {
|
||||
border-color: var(--color-primary);
|
||||
outline: 1px solid var(--color-primary);
|
||||
|
||||
.content {
|
||||
.indicator {
|
||||
svg {
|
||||
opacity: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.compact.checked {
|
||||
color: var(--color-text-link);
|
||||
border-color: var(--color-primary);
|
||||
|
||||
.content {
|
||||
.icon {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:first-child)::before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
width: 1px;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
bottom: -1px;
|
||||
background-color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Disabled Styles
|
||||
.radio.disabled {
|
||||
cursor: not-allowed;
|
||||
color: var(--color-disabled);
|
||||
|
||||
.content {
|
||||
.indicator {
|
||||
border-color: var(--color-disabled);
|
||||
|
||||
&::before {
|
||||
background: var(--color-layer-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card.disabled {
|
||||
background-color: var(--color-layer-2);
|
||||
border-color: var(--color-layer-2);
|
||||
outline: unset;
|
||||
}
|
||||
|
||||
.compact.disabled {
|
||||
cursor: not-allowed;
|
||||
background-color: var(--color-layer-2);
|
||||
|
||||
.content {
|
||||
.icon {
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not Disabled Behaviors
|
||||
.card:not(.disabled) {
|
||||
&:focus {
|
||||
outline: 1px solid var(--color-primary);
|
||||
box-shadow: var(--shadow-2);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: var(--shadow-2);
|
||||
}
|
||||
}
|
||||
|
||||
.compact:not(.disabled) {
|
||||
&:focus {
|
||||
color: var(--color-text-link);
|
||||
border-color: var(--color-primary);
|
||||
|
||||
.content {
|
||||
.icon {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--color-text-link);
|
||||
border-color: var(--color-primary);
|
||||
background-color: var(--color-hover-variant);
|
||||
|
||||
.content {
|
||||
.icon {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:first-child)::before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
width: 1px;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
bottom: -1px;
|
||||
background-color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ import type { KeyboardEventHandler, ReactNode } from 'react';
|
|||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
import * as styles from './Radio.module.scss';
|
||||
|
||||
const Check = () => (
|
||||
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
|
@ -27,6 +27,7 @@ export type Props = {
|
|||
type?: 'card' | 'plain' | 'compact';
|
||||
isDisabled?: boolean;
|
||||
disabledLabel?: AdminConsoleKey;
|
||||
icon?: ReactNode;
|
||||
};
|
||||
|
||||
const Radio = ({
|
||||
|
@ -38,9 +39,10 @@ const Radio = ({
|
|||
isChecked,
|
||||
onClick,
|
||||
tabIndex,
|
||||
type,
|
||||
type = 'plain',
|
||||
isDisabled,
|
||||
disabledLabel,
|
||||
icon,
|
||||
}: Props) => {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
||||
|
@ -62,6 +64,7 @@ const Radio = ({
|
|||
<div
|
||||
className={classNames(
|
||||
styles.radio,
|
||||
styles[type],
|
||||
isChecked && styles.checked,
|
||||
isDisabled && styles.disabled,
|
||||
className
|
||||
|
@ -81,6 +84,7 @@ const Radio = ({
|
|||
)}
|
||||
{children}
|
||||
{type === 'plain' && <div className={styles.indicator} />}
|
||||
{icon && <span className={styles.icon}>{icon}</span>}
|
||||
{title && t(title)}
|
||||
{isDisabled && disabledLabel && (
|
||||
<div className={classNames(styles.indicator, styles.disabledLabel)}>
|
||||
|
|
|
@ -13,194 +13,5 @@
|
|||
.compact {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
font: var(--font-body-2);
|
||||
align-items: center;
|
||||
|
||||
> .radio {
|
||||
position: relative;
|
||||
border: 1px solid var(--color-border);
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
flex: 1;
|
||||
|
||||
&:first-child {
|
||||
border-radius: 12px 0 0 12px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-radius: 0 12px 12px 0;
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
cursor: not-allowed;
|
||||
background-color: var(--color-layer-2);
|
||||
}
|
||||
|
||||
&:not(.disabled):focus {
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
|
||||
&:not(.disabled):hover {
|
||||
color: var(--color-text-link);
|
||||
font: var(--font-label-2);
|
||||
border-color: var(--color-primary);
|
||||
background-color: var(--color-hover-variant);
|
||||
|
||||
&:not(:first-child)::before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
width: 1px;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
bottom: -1px;
|
||||
background-color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: _.unit(5);
|
||||
}
|
||||
|
||||
&.checked {
|
||||
border-color: var(--color-primary);
|
||||
|
||||
&:not(:first-child)::before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
width: 1px;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
bottom: -1px;
|
||||
background-color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
/* stylelint-disable-next-line no-descending-specificity */
|
||||
> .radio {
|
||||
padding: _.unit(3);
|
||||
border-radius: _.unit(4);
|
||||
border: 1px solid transparent;
|
||||
outline: 1px solid var(--color-neutral-90);
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
|
||||
&.disabled {
|
||||
cursor: not-allowed;
|
||||
background-color: var(--color-layer-2);
|
||||
border-color: var(--color-layer-2);
|
||||
outline: unset;
|
||||
}
|
||||
|
||||
&:not(.disabled):focus {
|
||||
outline: 1px solid var(--color-primary);
|
||||
box-shadow: var(--shadow-2);
|
||||
}
|
||||
|
||||
&:not(.disabled):hover {
|
||||
box-shadow: var(--shadow-2);
|
||||
}
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
|
||||
.indicator {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
|
||||
svg {
|
||||
opacity: 0%;
|
||||
}
|
||||
}
|
||||
|
||||
.disabledLabel {
|
||||
background: var(--color-neutral-90);
|
||||
padding: _.unit(0.5) _.unit(2);
|
||||
border-radius: 10px;
|
||||
font: var(--font-label-3);
|
||||
color: var(--color-text);
|
||||
}
|
||||
}
|
||||
|
||||
&.checked {
|
||||
border-color: var(--color-primary);
|
||||
outline: 1px solid var(--color-primary);
|
||||
|
||||
.indicator {
|
||||
svg {
|
||||
opacity: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.plain {
|
||||
font: var(--font-body-2);
|
||||
|
||||
/* stylelint-disable-next-line no-descending-specificity */
|
||||
> .radio {
|
||||
cursor: pointer;
|
||||
|
||||
/* stylelint-disable-next-line no-descending-specificity */
|
||||
&:not(:last-child) {
|
||||
margin-bottom: _.unit(2);
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.indicator {
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--color-neutral-60);
|
||||
display: inline-block;
|
||||
margin-right: _.unit(2);
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
background: var(--color-layer-1);
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--color-layer-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.checked {
|
||||
.content {
|
||||
.indicator {
|
||||
border-color: var(--color-primary);
|
||||
|
||||
&::before {
|
||||
background: var(--color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
cursor: not-allowed;
|
||||
color: var(--color-disabled);
|
||||
|
||||
.content {
|
||||
.indicator {
|
||||
border-color: var(--color-disabled);
|
||||
|
||||
&::before {
|
||||
background: var(--color-layer-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue