mirror of
https://github.com/logto-io/logto.git
synced 2025-01-27 21:39:16 -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 { useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import * as styles from './index.module.scss';
|
import * as styles from './Radio.module.scss';
|
||||||
|
|
||||||
const Check = () => (
|
const Check = () => (
|
||||||
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<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';
|
type?: 'card' | 'plain' | 'compact';
|
||||||
isDisabled?: boolean;
|
isDisabled?: boolean;
|
||||||
disabledLabel?: AdminConsoleKey;
|
disabledLabel?: AdminConsoleKey;
|
||||||
|
icon?: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Radio = ({
|
const Radio = ({
|
||||||
|
@ -38,9 +39,10 @@ const Radio = ({
|
||||||
isChecked,
|
isChecked,
|
||||||
onClick,
|
onClick,
|
||||||
tabIndex,
|
tabIndex,
|
||||||
type,
|
type = 'plain',
|
||||||
isDisabled,
|
isDisabled,
|
||||||
disabledLabel,
|
disabledLabel,
|
||||||
|
icon,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||||
|
|
||||||
|
@ -62,6 +64,7 @@ const Radio = ({
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
styles.radio,
|
styles.radio,
|
||||||
|
styles[type],
|
||||||
isChecked && styles.checked,
|
isChecked && styles.checked,
|
||||||
isDisabled && styles.disabled,
|
isDisabled && styles.disabled,
|
||||||
className
|
className
|
||||||
|
@ -81,6 +84,7 @@ const Radio = ({
|
||||||
)}
|
)}
|
||||||
{children}
|
{children}
|
||||||
{type === 'plain' && <div className={styles.indicator} />}
|
{type === 'plain' && <div className={styles.indicator} />}
|
||||||
|
{icon && <span className={styles.icon}>{icon}</span>}
|
||||||
{title && t(title)}
|
{title && t(title)}
|
||||||
{isDisabled && disabledLabel && (
|
{isDisabled && disabledLabel && (
|
||||||
<div className={classNames(styles.indicator, styles.disabledLabel)}>
|
<div className={classNames(styles.indicator, styles.disabledLabel)}>
|
||||||
|
|
|
@ -13,194 +13,5 @@
|
||||||
.compact {
|
.compact {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
font: var(--font-body-2);
|
|
||||||
align-items: center;
|
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