Add Group type with id, name, description, members array and optional user_ids field. Add name field to policy targets for display. Add groups API client methods for list, create, update and delete operations. Add GroupsPage component with create form, edit modal, member selection and table view. Add groups route and navigation item to Layout. Add reusable Modal component with title, subtitle and close handler. Update
422 lines
6.4 KiB
CSS
422 lines
6.4 KiB
CSS
:root {
|
|
color-scheme: light dark;
|
|
--bg: #0c1322;
|
|
--bg-soft: #111b30;
|
|
--panel: rgba(17, 27, 48, 0.78);
|
|
--panel-strong: #14203a;
|
|
--text: #eff4ff;
|
|
--muted: #9fb2d4;
|
|
--line: rgba(177, 197, 229, 0.15);
|
|
--accent: #74e0b8;
|
|
--accent-strong: #1fb67a;
|
|
--shadow: 0 18px 48px rgba(3, 8, 20, 0.35);
|
|
font-family: "Segoe UI", "SF Pro Text", "Helvetica Neue", sans-serif;
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
min-height: 100vh;
|
|
color: var(--text);
|
|
background:
|
|
radial-gradient(circle at top left, rgba(116, 224, 184, 0.17), transparent 28%),
|
|
radial-gradient(circle at bottom right, rgba(98, 144, 255, 0.16), transparent 24%),
|
|
linear-gradient(180deg, #08101d 0%, #0d1728 100%);
|
|
}
|
|
|
|
a {
|
|
color: inherit;
|
|
text-decoration: none;
|
|
}
|
|
|
|
button {
|
|
font: inherit;
|
|
}
|
|
|
|
.shell {
|
|
display: grid;
|
|
grid-template-columns: 280px 1fr;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.auth-shell {
|
|
min-height: 100vh;
|
|
display: grid;
|
|
place-items: center;
|
|
padding: 24px;
|
|
}
|
|
|
|
.auth-card {
|
|
width: min(460px, 100%);
|
|
display: grid;
|
|
gap: 16px;
|
|
padding: 28px;
|
|
background: var(--panel);
|
|
border: 1px solid var(--line);
|
|
border-radius: 24px;
|
|
box-shadow: var(--shadow);
|
|
backdrop-filter: blur(12px);
|
|
}
|
|
|
|
.auth-brand,
|
|
.brand-block,
|
|
.topbar-brand,
|
|
.topbar-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 16px;
|
|
}
|
|
|
|
.auth-brand {
|
|
align-items: flex-start;
|
|
gap: 18px;
|
|
}
|
|
|
|
.auth-brand-copy {
|
|
display: grid;
|
|
gap: 8px;
|
|
min-width: 0;
|
|
}
|
|
|
|
.auth-brand-copy h2 {
|
|
margin: 0;
|
|
line-height: 1.1;
|
|
}
|
|
|
|
.brand-block {
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.brand-copy {
|
|
display: grid;
|
|
gap: 6px;
|
|
}
|
|
|
|
.brand-tagline {
|
|
margin: 0;
|
|
color: var(--muted);
|
|
max-width: 240px;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.brand-logo {
|
|
display: block;
|
|
height: auto;
|
|
}
|
|
|
|
.brand-logo-full {
|
|
width: min(100%, 220px);
|
|
}
|
|
|
|
.auth-brand .brand-logo-full {
|
|
width: 200px;
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.brand-logo-mark {
|
|
width: 48px;
|
|
border-radius: 14px;
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
|
|
}
|
|
|
|
.auth-card label {
|
|
display: grid;
|
|
gap: 8px;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.auth-card input {
|
|
border: 1px solid var(--line);
|
|
background: rgba(8, 14, 26, 0.86);
|
|
color: var(--text);
|
|
border-radius: 14px;
|
|
padding: 14px 16px;
|
|
}
|
|
|
|
.auth-copy {
|
|
margin: 0;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.sidebar {
|
|
padding: 28px;
|
|
border-right: 1px solid var(--line);
|
|
background: rgba(7, 12, 22, 0.76);
|
|
backdrop-filter: blur(18px);
|
|
}
|
|
|
|
.nav {
|
|
display: grid;
|
|
gap: 10px;
|
|
margin-top: 40px;
|
|
}
|
|
|
|
.nav-link {
|
|
padding: 12px 14px;
|
|
border-radius: 14px;
|
|
color: var(--muted);
|
|
transition: 180ms ease;
|
|
}
|
|
|
|
.nav-link:hover,
|
|
.nav-link.active {
|
|
color: var(--text);
|
|
background: rgba(116, 224, 184, 0.12);
|
|
}
|
|
|
|
.content {
|
|
padding: 28px;
|
|
}
|
|
|
|
.topbar,
|
|
.page-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
gap: 16px;
|
|
}
|
|
|
|
.page {
|
|
display: grid;
|
|
gap: 22px;
|
|
}
|
|
|
|
.grid {
|
|
display: grid;
|
|
gap: 18px;
|
|
}
|
|
|
|
.grid.two {
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
}
|
|
|
|
.grid.three {
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
}
|
|
|
|
.card,
|
|
.table-wrap {
|
|
background: var(--panel);
|
|
border: 1px solid var(--line);
|
|
border-radius: 24px;
|
|
padding: 22px;
|
|
box-shadow: var(--shadow);
|
|
backdrop-filter: blur(12px);
|
|
}
|
|
|
|
.table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
.table th,
|
|
.table td {
|
|
text-align: left;
|
|
padding: 14px 10px;
|
|
border-bottom: 1px solid var(--line);
|
|
}
|
|
|
|
.table tbody tr:last-child td {
|
|
border-bottom: 0;
|
|
}
|
|
|
|
.inline-form {
|
|
display: grid;
|
|
gap: 12px;
|
|
grid-template-columns: repeat(6, minmax(0, 1fr));
|
|
align-items: center;
|
|
}
|
|
|
|
.stacked-form {
|
|
display: grid;
|
|
gap: 14px;
|
|
}
|
|
|
|
.stacked-form input,
|
|
.stacked-form select {
|
|
width: 100%;
|
|
border: 1px solid var(--line);
|
|
background: rgba(8, 14, 26, 0.86);
|
|
color: var(--text);
|
|
border-radius: 14px;
|
|
padding: 12px 14px;
|
|
}
|
|
|
|
.form-grid {
|
|
display: grid;
|
|
gap: 12px;
|
|
}
|
|
|
|
.form-grid.two {
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
}
|
|
|
|
.inline-form input,
|
|
.inline-form select {
|
|
width: 100%;
|
|
border: 1px solid var(--line);
|
|
background: rgba(8, 14, 26, 0.86);
|
|
color: var(--text);
|
|
border-radius: 14px;
|
|
padding: 12px 14px;
|
|
}
|
|
|
|
.checkbox {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.button,
|
|
.pill {
|
|
border: 0;
|
|
padding: 11px 16px;
|
|
border-radius: 999px;
|
|
background: linear-gradient(135deg, var(--accent) 0%, var(--accent-strong) 100%);
|
|
color: #04141a;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.ghost-button {
|
|
border: 1px solid var(--line);
|
|
padding: 11px 16px;
|
|
border-radius: 999px;
|
|
background: transparent;
|
|
color: var(--text);
|
|
}
|
|
|
|
.pill {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.eyebrow {
|
|
margin: 0 0 8px;
|
|
color: var(--accent);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.16em;
|
|
font-size: 0.75rem;
|
|
}
|
|
|
|
.metric-label,
|
|
.page-header p,
|
|
.card p {
|
|
color: var(--muted);
|
|
}
|
|
|
|
.metric-value {
|
|
display: block;
|
|
margin: 10px 0;
|
|
font-size: 2rem;
|
|
}
|
|
|
|
.notice {
|
|
margin: 0;
|
|
color: #ffcf9b;
|
|
}
|
|
|
|
.code-block {
|
|
overflow: auto;
|
|
border-radius: 16px;
|
|
padding: 16px;
|
|
background: rgba(8, 14, 26, 0.92);
|
|
border: 1px solid var(--line);
|
|
white-space: pre-wrap;
|
|
}
|
|
|
|
.action-row {
|
|
display: flex;
|
|
gap: 12px;
|
|
}
|
|
|
|
.selection-panel {
|
|
display: grid;
|
|
gap: 10px;
|
|
padding: 16px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 18px;
|
|
background: rgba(8, 14, 26, 0.56);
|
|
}
|
|
|
|
.selection-list {
|
|
display: grid;
|
|
gap: 10px;
|
|
max-height: 240px;
|
|
overflow: auto;
|
|
}
|
|
|
|
.selection-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
color: var(--text);
|
|
}
|
|
|
|
.modal-backdrop {
|
|
position: fixed;
|
|
inset: 0;
|
|
display: grid;
|
|
place-items: center;
|
|
padding: 24px;
|
|
background: rgba(2, 6, 15, 0.72);
|
|
backdrop-filter: blur(10px);
|
|
z-index: 50;
|
|
}
|
|
|
|
.modal-card {
|
|
width: min(640px, 100%);
|
|
max-height: calc(100vh - 48px);
|
|
overflow: auto;
|
|
display: grid;
|
|
gap: 18px;
|
|
padding: 24px;
|
|
background: #111b30;
|
|
border: 1px solid var(--line);
|
|
border-radius: 24px;
|
|
box-shadow: var(--shadow);
|
|
}
|
|
|
|
.modal-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
gap: 16px;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
@media (max-width: 960px) {
|
|
.shell {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.sidebar {
|
|
border-right: 0;
|
|
border-bottom: 1px solid var(--line);
|
|
}
|
|
|
|
.auth-brand,
|
|
.brand-block,
|
|
.topbar-brand,
|
|
.topbar-actions,
|
|
.page-header {
|
|
align-items: flex-start;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.brand-logo-full {
|
|
width: min(100%, 200px);
|
|
}
|
|
|
|
.grid.two,
|
|
.grid.three {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.inline-form {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|