mirror of
https://github.com/logto-io/logto.git
synced 2025-03-31 22:51:25 -05:00
style(experience): update scopes and organizations selector style (#5289)
update the scopes and organizations selector style
This commit is contained in:
parent
6a9ce098d6
commit
09de2996d0
9 changed files with 68 additions and 75 deletions
|
@ -1,4 +1,4 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.575 11.9083L9.99999 15.4916L6.42499 11.9083C6.26807 11.7514 6.05524 11.6632 5.83333 11.6632C5.61141 11.6632 5.39858 11.7514 5.24166 11.9083C5.08474 12.0652 4.99658 12.278 4.99658 12.4999C4.99658 12.7219 5.08474 12.9347 5.24166 13.0916L9.40833 17.2583C9.48579 17.3364 9.57796 17.3984 9.67951 17.4407C9.78106 17.483 9.88998 17.5048 9.99999 17.5048C10.11 17.5048 10.2189 17.483 10.3205 17.4407C10.422 17.3984 10.5142 17.3364 10.5917 17.2583L14.7583 13.0916C14.836 13.0139 14.8977 12.9217 14.9397 12.8202C14.9818 12.7186 15.0034 12.6098 15.0034 12.4999C15.0034 12.3901 14.9818 12.2813 14.9397 12.1797C14.8977 12.0782 14.836 11.986 14.7583 11.9083C14.6806 11.8306 14.5884 11.7689 14.4869 11.7269C14.3853 11.6848 14.2765 11.6632 14.1667 11.6632C14.0568 11.6632 13.948 11.6848 13.8465 11.7269C13.7449 11.7689 13.6527 11.8306 13.575 11.9083ZM6.42499 8.09162L9.99999 4.50828L13.575 8.09162C13.6525 8.16972 13.7446 8.23172 13.8462 8.27402C13.9477 8.31633 14.0566 8.33811 14.1667 8.33811C14.2767 8.33811 14.3856 8.31633 14.4871 8.27402C14.5887 8.23172 14.6809 8.16972 14.7583 8.09162C14.8364 8.01415 14.8984 7.92198 14.9407 7.82043C14.983 7.71888 15.0048 7.60996 15.0048 7.49995C15.0048 7.38994 14.983 7.28102 14.9407 7.17947C14.8984 7.07792 14.8364 6.98575 14.7583 6.90828L10.5917 2.74162C10.5142 2.66351 10.422 2.60151 10.3205 2.55921C10.2189 2.5169 10.11 2.49512 9.99999 2.49512C9.88998 2.49512 9.78106 2.5169 9.67951 2.55921C9.57796 2.60151 9.48579 2.66351 9.40833 2.74162L5.24166 6.90828C5.08474 7.0652 4.99658 7.27803 4.99658 7.49995C4.99658 7.72187 5.08474 7.9347 5.24166 8.09162C5.39858 8.24854 5.61141 8.33669 5.83333 8.33669C6.05524 8.33669 6.26807 8.24854 6.42499 8.09162Z" fill="currentcolor" fill-opacity="0.35"/>
|
||||
<path d="M13.575 11.9083L9.99999 15.4916L6.42499 11.9083C6.26807 11.7514 6.05524 11.6632 5.83333 11.6632C5.61141 11.6632 5.39858 11.7514 5.24166 11.9083C5.08474 12.0652 4.99658 12.278 4.99658 12.4999C4.99658 12.7219 5.08474 12.9347 5.24166 13.0916L9.40833 17.2583C9.48579 17.3364 9.57796 17.3984 9.67951 17.4407C9.78106 17.483 9.88998 17.5048 9.99999 17.5048C10.11 17.5048 10.2189 17.483 10.3205 17.4407C10.422 17.3984 10.5142 17.3364 10.5917 17.2583L14.7583 13.0916C14.836 13.0139 14.8977 12.9217 14.9397 12.8202C14.9818 12.7186 15.0034 12.6098 15.0034 12.4999C15.0034 12.3901 14.9818 12.2813 14.9397 12.1797C14.8977 12.0782 14.836 11.986 14.7583 11.9083C14.6806 11.8306 14.5884 11.7689 14.4869 11.7269C14.3853 11.6848 14.2765 11.6632 14.1667 11.6632C14.0568 11.6632 13.948 11.6848 13.8465 11.7269C13.7449 11.7689 13.6527 11.8306 13.575 11.9083ZM6.42499 8.09162L9.99999 4.50828L13.575 8.09162C13.6525 8.16972 13.7446 8.23172 13.8462 8.27402C13.9477 8.31633 14.0566 8.33811 14.1667 8.33811C14.2767 8.33811 14.3856 8.31633 14.4871 8.27402C14.5887 8.23172 14.6809 8.16972 14.7583 8.09162C14.8364 8.01415 14.8984 7.92198 14.9407 7.82043C14.983 7.71888 15.0048 7.60996 15.0048 7.49995C15.0048 7.38994 14.983 7.28102 14.9407 7.17947C14.8984 7.07792 14.8364 6.98575 14.7583 6.90828L10.5917 2.74162C10.5142 2.66351 10.422 2.60151 10.3205 2.55921C10.2189 2.5169 10.11 2.49512 9.99999 2.49512C9.88998 2.49512 9.78106 2.5169 9.67951 2.55921C9.57796 2.60151 9.48579 2.66351 9.40833 2.74162L5.24166 6.90828C5.08474 7.0652 4.99658 7.27803 4.99658 7.49995C4.99658 7.72187 5.08474 7.9347 5.24166 8.09162C5.39858 8.24854 5.61141 8.33669 5.83333 8.33669C6.05524 8.33669 6.26807 8.24854 6.42499 8.09162Z" fill="currentcolor" />
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
@ -1,8 +1,9 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.organizationItem {
|
||||
@include _.flex-row;
|
||||
padding: _.unit(2) _.unit(4);
|
||||
border-radius: _.unit(2);
|
||||
padding: _.unit(2.5) _.unit(2);
|
||||
cursor: pointer;
|
||||
|
||||
.icon {
|
||||
width: 20px;
|
||||
|
@ -16,12 +17,8 @@
|
|||
flex: 1;
|
||||
}
|
||||
|
||||
&[role='button'] {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--color-overlay-brand-hover);
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--color-overlay-neutral-hover);
|
||||
}
|
||||
|
||||
&[data-selected='true'] {
|
||||
|
@ -31,4 +28,5 @@
|
|||
color: var(--color-brand-default);
|
||||
}
|
||||
}
|
||||
@include _.flex-row;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { type ConsentInfoResponse } from '@logto/schemas';
|
||||
import classNames from 'classnames';
|
||||
import { type ReactNode } from 'react';
|
||||
|
||||
import CheckMark from '@/assets/icons/check-mark.svg';
|
||||
|
@ -10,6 +11,7 @@ import * as styles from './index.module.scss';
|
|||
export type Organization = Exclude<ConsentInfoResponse['organizations'], undefined>[number];
|
||||
|
||||
type OrganizationItemProps = {
|
||||
className?: string;
|
||||
organization: Organization;
|
||||
onSelect?: (organization: Organization) => void;
|
||||
isSelected?: boolean;
|
||||
|
@ -21,10 +23,11 @@ const OrganizationItem = ({
|
|||
onSelect,
|
||||
isSelected,
|
||||
suffixElement,
|
||||
className,
|
||||
}: OrganizationItemProps) => {
|
||||
return (
|
||||
<div
|
||||
className={styles.organizationItem}
|
||||
className={classNames(styles.organizationItem, className)}
|
||||
data-selected={isSelected}
|
||||
{...(onSelect && {
|
||||
role: 'button',
|
||||
|
@ -32,16 +35,9 @@ const OrganizationItem = ({
|
|||
onClick: () => {
|
||||
onSelect(organization);
|
||||
},
|
||||
onKeyDown: () => {
|
||||
onKeyDownHandler({
|
||||
Enter: () => {
|
||||
onSelect(organization);
|
||||
},
|
||||
' ': () => {
|
||||
onSelect(organization);
|
||||
},
|
||||
});
|
||||
},
|
||||
onKeyDown: onKeyDownHandler(() => {
|
||||
onSelect(organization);
|
||||
}),
|
||||
})}
|
||||
>
|
||||
{isSelected ? (
|
||||
|
|
|
@ -11,10 +11,13 @@
|
|||
border: _.border(var(--color-line-divider));
|
||||
box-shadow: var(--color-shadow-2);
|
||||
border-radius: _.unit(2);
|
||||
background-color: var(--color-bg-float);
|
||||
background: var(--color-bg-float);
|
||||
position: absolute;
|
||||
z-index: 50;
|
||||
padding: _.unit(2) 0;
|
||||
|
||||
.container {
|
||||
padding: _.unit(2);
|
||||
}
|
||||
}
|
||||
|
||||
:global(body.mobile) {
|
||||
|
@ -31,8 +34,16 @@
|
|||
border-bottom-right-radius: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
padding: _.unit(4) 0;
|
||||
min-height: 200px;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
|
||||
.container {
|
||||
padding: _.unit(3) _.unit(1);
|
||||
}
|
||||
}
|
||||
|
||||
.organizationItem {
|
||||
padding: _.unit(3);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,17 +65,20 @@ const OrganizationSelectorModal = ({
|
|||
closeTimeoutMS={isMobile ? 300 : 0}
|
||||
onRequestClose={onClose}
|
||||
>
|
||||
{organizations.map((organization) => (
|
||||
<OrganizationItem
|
||||
key={organization.id}
|
||||
organization={organization}
|
||||
isSelected={organization.id === selectedOrganization.id}
|
||||
onSelect={() => {
|
||||
onClose();
|
||||
onSelect(organization);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<div className={styles.container}>
|
||||
{organizations.map((organization) => (
|
||||
<OrganizationItem
|
||||
key={organization.id}
|
||||
className={styles.organizationItem}
|
||||
organization={organization}
|
||||
isSelected={organization.id === selectedOrganization.id}
|
||||
onSelect={() => {
|
||||
onClose();
|
||||
onSelect(organization);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</ReactModal>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -8,28 +8,25 @@
|
|||
.cardWrapper {
|
||||
border: _.border(var(--color-line-divider));
|
||||
border-radius: 8px;
|
||||
padding: _.unit(2) 0;
|
||||
padding: _.unit(2);
|
||||
position: relative;
|
||||
|
||||
&[data-active='true'] {
|
||||
border-color: var(--color-brand-default);
|
||||
outline: 3px solid var(--color-overlay-brand-focused);
|
||||
}
|
||||
}
|
||||
|
||||
.expandButton {
|
||||
position: relative;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
color: var(--color-type-disable);
|
||||
}
|
||||
|
||||
// increase the clickable area
|
||||
&::after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
left: -10px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
color: var(--color-type-secondary);
|
||||
.selectedOrganization {
|
||||
&:hover {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import { useState, useRef } from 'react';
|
|||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import ExpandableIcon from '@/assets/icons/expandable-icon.svg';
|
||||
import IconButton from '@/components/Button/IconButton';
|
||||
|
||||
import OrganizationItem, { type Organization } from './OrganizationItem';
|
||||
import OrganizationSelectorModal from './OrganizationSelectorModal';
|
||||
|
@ -33,19 +32,14 @@ const OrganizationSelector = ({
|
|||
return (
|
||||
<div className={className}>
|
||||
<div className={styles.title}>{t('description.grant_organization_access')}</div>
|
||||
<div ref={parentElementRef} className={styles.cardWrapper}>
|
||||
<div ref={parentElementRef} className={styles.cardWrapper} data-active={showDropdown}>
|
||||
<OrganizationItem
|
||||
className={styles.selectedOrganization}
|
||||
organization={selectedOrganization}
|
||||
suffixElement={
|
||||
<IconButton
|
||||
className={styles.expandButton}
|
||||
onClick={() => {
|
||||
setShowDropdown(true);
|
||||
}}
|
||||
>
|
||||
<ExpandableIcon />
|
||||
</IconButton>
|
||||
}
|
||||
suffixElement={<ExpandableIcon className={styles.expandButton} />}
|
||||
onSelect={() => {
|
||||
setShowDropdown(true);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<OrganizationSelectorModal
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
@include _.flex-row;
|
||||
border-radius: _.unit(2);
|
||||
padding: _.unit(2);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--color-overlay-neutral-hover);
|
||||
|
@ -40,11 +41,9 @@
|
|||
.toggleButton {
|
||||
transition: transform 0.2s ease-in-out;
|
||||
position: relative;
|
||||
|
||||
svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
color: var(--color-type-disable);
|
||||
|
||||
&[data-expanded='true'] {
|
||||
transform: rotate(180deg);
|
||||
|
|
|
@ -6,7 +6,6 @@ import { Trans, useTranslation } from 'react-i18next';
|
|||
|
||||
import DownArrowIcon from '@/assets/icons/arrow-down.svg';
|
||||
import CheckMark from '@/assets/icons/check-mark.svg';
|
||||
import IconButton from '@/components/Button/IconButton';
|
||||
import TermsLinks from '@/components/TermsLinks';
|
||||
import { onKeyDownHandler } from '@/utils/a11y';
|
||||
|
||||
|
@ -36,15 +35,11 @@ const ScopeGroup = ({ groupName, scopes, isAutoExpand = false }: ScopeGroupProps
|
|||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={toggle}
|
||||
onKeyDown={onKeyDownHandler({
|
||||
Enter: toggle,
|
||||
})}
|
||||
onKeyDown={onKeyDownHandler(toggle)}
|
||||
>
|
||||
<CheckMark className={styles.check} />
|
||||
<div className={styles.scopeGroupName}>{groupName}</div>
|
||||
<IconButton className={styles.toggleButton} data-expanded={expanded}>
|
||||
<DownArrowIcon />
|
||||
</IconButton>
|
||||
<DownArrowIcon className={styles.toggleButton} data-expanded={expanded} />
|
||||
</div>
|
||||
{expanded && (
|
||||
<ul className={styles.scopesList}>
|
||||
|
|
Loading…
Add table
Reference in a new issue