diff --git a/.server-changes/sso-directory-sync-ui.md b/.server-changes/sso-directory-sync-ui.md new file mode 100644 index 0000000000..45d28ba71c --- /dev/null +++ b/.server-changes/sso-directory-sync-ui.md @@ -0,0 +1,6 @@ +--- +area: webapp +type: improvement +--- + +Refreshed the SSO & Directory Sync settings page layout and copy diff --git a/apps/webapp/app/components/LoginPageLayout.tsx b/apps/webapp/app/components/LoginPageLayout.tsx index e48489fd90..bf66c25b12 100644 --- a/apps/webapp/app/components/LoginPageLayout.tsx +++ b/apps/webapp/app/components/LoginPageLayout.tsx @@ -52,7 +52,9 @@ export function LoginPageLayout({ children }: { children: React.ReactNode }) { -
{children}
+
+
{children}
+
Having login issues? Email us or{" "} ask us in Discord diff --git a/apps/webapp/app/components/navigation/OrganizationSettingsSideMenu.tsx b/apps/webapp/app/components/navigation/OrganizationSettingsSideMenu.tsx index dc59cc720b..4158d30945 100644 --- a/apps/webapp/app/components/navigation/OrganizationSettingsSideMenu.tsx +++ b/apps/webapp/app/components/navigation/OrganizationSettingsSideMenu.tsx @@ -149,7 +149,7 @@ export function OrganizationSettingsSideMenu({ )} {isSsoUsingPlugin && ( extends Om allowItemShortcuts?: boolean; clearSearchOnSelection?: boolean; dropdownIcon?: boolean | React.ReactNode; + popoverClassName?: string; + placement?: Ariakit.SelectProviderProps["placement"]; } export function Select({ @@ -135,6 +137,8 @@ export function Select({ disabled, clearSearchOnSelection = true, dropdownIcon, + popoverClassName, + placement, ...props }: SelectProps) { const [searchValue, setSearchValue] = useState(""); @@ -191,6 +195,7 @@ export function Select({ open={open} setOpen={setOpen} virtualFocus={searchable} + placement={placement} value={value} setValue={(v) => { if (clearSearchOnSelection) { @@ -215,7 +220,7 @@ export function Select({ dropdownIcon={dropdownIcon} {...props} /> - + {!searchable && showHeading && heading && {heading}} />} {searchable && } @@ -437,7 +442,7 @@ export function SelectList(props: SelectListProps) { @@ -449,6 +454,9 @@ export interface SelectItemProps extends Ariakit.SelectItemProps { checkIcon?: React.ReactNode; checkPosition?: "left" | "right"; shortcut?: ShortcutDefinition; + // Allow the item to grow to multiple lines and wrap its content instead of + // being locked to a single truncated line. Use for options with a subtitle. + wrap?: boolean; } const selectItemClasses = @@ -461,6 +469,7 @@ export function SelectItem({ checkIcon = , checkPosition = "right", shortcut, + wrap = false, ...props }: SelectItemProps) { const combobox = Ariakit.useComboboxContext(); @@ -508,13 +517,16 @@ export function SelectItem({ >
{checkPosition === "left" && } {icon} -
{props.children || props.value}
+
+ {props.children || props.value} +
{checkPosition === "right" && checkIcon} {shortcut && ( + {children} + + ); +} + +/** A group of related rows. Adds vertical spacing between sibling sections. */ +export function SettingsSection({ + children, + className, +}: { + children: ReactNode; + className?: string; +}) { + return ( +
{children}
+ ); +} + +/** + * Section (or sub-section) heading with an optional description and a + * right-aligned action, sitting above a bottom divide. Use `as="h3"` for a + * heading nested inside a section. + */ +export function SettingsHeader({ + title, + description, + action, + as = "h2", + className, +}: { + title: ReactNode; + description?: ReactNode; + action?: ReactNode; + as?: "h2" | "h3"; + className?: string; +}) { + const Heading = as === "h3" ? Header3 : Header2; + return ( +
+
+ {title} + {description ? {description} : null} +
+ {action ?
{action}
: null} +
+ ); +} + +/** Title typography for a row. Renders a `