├── README.md ├── src ├── pages │ ├── applications │ │ ├── [id].astro │ │ └── index.astro │ ├── 404.astro │ ├── users │ │ └── index.astro │ └── index.astro ├── styles │ ├── abstract │ │ ├── functions │ │ │ ├── _index.scss │ │ │ └── _pxToRem.scss │ │ ├── variables │ │ │ ├── _index.scss │ │ │ ├── _common.scss │ │ │ └── _devices.scss │ │ ├── _index.scss │ │ └── mixins │ │ │ ├── _index.scss │ │ │ ├── _trim.scss │ │ │ ├── _break-word.scss │ │ │ └── _scroll.scss │ ├── 5-animations │ │ ├── _index.scss │ │ ├── _rotate.scss │ │ └── _bounce.scss │ ├── global.css │ ├── 1-css-variables │ │ ├── _common.scss │ │ ├── _index.scss │ │ ├── _language.scss │ │ ├── _border-radius.scss │ │ ├── _sizes.scss │ │ ├── _fonts.scss │ │ ├── _shadows.scss │ │ └── _colors.scss │ ├── 6-elements │ │ ├── form │ │ │ ├── _optional.scss │ │ │ ├── _notification.scss │ │ │ ├── _index.scss │ │ │ ├── _helper.scss │ │ │ ├── _label.scss │ │ │ ├── _placeholder.scss │ │ │ ├── _pulse-notification.scss │ │ │ ├── _form.scss │ │ │ ├── _password-meter.scss │ │ │ ├── _interactive-text-output.scss │ │ │ ├── _switch.scss │ │ │ └── _radio-and-checkbox.scss │ │ ├── _divider.scss │ │ ├── _logo.scss │ │ ├── _link.scss │ │ ├── _index.scss │ │ ├── _inline-code.scss │ │ ├── _kbd.scss │ │ ├── _container.scss │ │ ├── _image-item.scss │ │ ├── _tooltip.scss │ │ ├── _inline-tag.scss │ │ ├── _box.scss │ │ ├── _loader.scss │ │ ├── _card.scss │ │ ├── _table.scss │ │ ├── _tag.scss │ │ ├── _avatar.scss │ │ └── _button.scss │ ├── _4-icons.scss │ ├── custom.scss │ ├── 8-grids │ │ ├── _grid-300px-1fr.scss │ │ ├── _grid-1-2.scss │ │ ├── _grid-2-1.scss │ │ ├── _inner-grid.scss │ │ ├── _index.scss │ │ ├── _grid-code.scss │ │ ├── _grid-header.scss │ │ ├── _cover-frame.scss │ │ ├── _grid-box.scss │ │ ├── _grid-dashboard-1s-2m-6l.scss │ │ ├── _grid-1-1.scss │ │ ├── _wizard-secondary.scss │ │ ├── _grid-with-side.scss │ │ └── _wizard.scss │ ├── 2-resets │ │ ├── _index.scss │ │ ├── _custom-css-reset.scss │ │ └── _typography.scss │ ├── 7-components │ │ ├── _main-footer.scss │ │ ├── _inline-links.scss │ │ ├── _breadcrumbs.scss │ │ ├── _status.scss │ │ ├── _pagination.scss │ │ ├── _index.scss │ │ ├── _grid-item-1.scss │ │ ├── _buttons-list.scss │ │ ├── _top-cover.scss │ │ ├── _tab-text-ediror.scss │ │ ├── _code-panel.scss │ │ ├── _action-bar.scss │ │ ├── _file-preview.scss │ │ ├── _clickable-list.scss │ │ ├── _top-banner.scss │ │ ├── _secondary-tabs.scss │ │ ├── _toggle-button.scss │ │ ├── _user-profile.scss │ │ ├── _progress-bar.scss │ │ ├── _main-header.scss │ │ ├── _upload-image.scss │ │ ├── _upload-file-box.scss │ │ ├── _list.scss │ │ ├── _collapsible.scss │ │ ├── _upload-box.scss │ │ ├── _alert-sticky.scss │ │ ├── _alert.scss │ │ ├── _side-nav.scss │ │ ├── _tabs.scss │ │ ├── _steps.scss │ │ ├── _modal.scss │ │ └── _drop.scss │ ├── _index.scss │ └── theme.scss ├── sdk │ ├── enums.ts │ ├── abstract.ts │ ├── proto │ │ ├── database.proto │ │ ├── broadcast.proto │ │ ├── system.proto │ │ └── application.proto │ ├── package.json │ ├── events.ts │ ├── core.ts │ ├── test.ts │ └── index.ts ├── assets │ ├── background.svg │ └── astro.svg └── layouts │ └── Layout.astro ├── license ├── COMMERCIAL.MD ├── NON-COMMERCIAL.MD └── README.MD ├── .vscode ├── extensions.json └── launch.json ├── tsconfig.json ├── .gitignore ├── package.json ├── tailwind.config.js ├── public └── favicon.svg └── astro.config.mjs /README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/applications/[id].astro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /license/COMMERCIAL.MD: -------------------------------------------------------------------------------- 1 | // TODO: Do this license -------------------------------------------------------------------------------- /license/NON-COMMERCIAL.MD: -------------------------------------------------------------------------------- 1 | // TODO: Do this license -------------------------------------------------------------------------------- /src/styles/abstract/functions/_index.scss: -------------------------------------------------------------------------------- 1 | @forward "pxToRem"; -------------------------------------------------------------------------------- /src/styles/5-animations/_index.scss: -------------------------------------------------------------------------------- 1 | @forward "bounce"; 2 | @forward "rotate"; -------------------------------------------------------------------------------- /src/styles/abstract/variables/_index.scss: -------------------------------------------------------------------------------- 1 | @forward "common"; 2 | @forward "devices"; -------------------------------------------------------------------------------- /src/styles/global.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /src/styles/abstract/_index.scss: -------------------------------------------------------------------------------- 1 | @forward "variables"; 2 | @forward "mixins"; 3 | @forward "functions"; -------------------------------------------------------------------------------- /src/styles/abstract/mixins/_index.scss: -------------------------------------------------------------------------------- 1 | @forward "trim"; 2 | @forward "break-word"; 3 | 4 | @forward "scroll"; -------------------------------------------------------------------------------- /src/styles/abstract/variables/_common.scss: -------------------------------------------------------------------------------- 1 | $theme-dark: ".theme-dark"; 2 | $disabled: ":disabled, .is-disabled"; -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /src/styles/1-css-variables/_common.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | /* common CSS native variables */ 3 | :root { 4 | --transition: 0.2s; 5 | } -------------------------------------------------------------------------------- /src/styles/6-elements/form/_optional.scss: -------------------------------------------------------------------------------- 1 | @use "../../abstract" as *; 2 | .optional { 3 | color: hsl(var(--color-neutral-50)); 4 | font-size: pxToRem(14); 5 | } 6 | -------------------------------------------------------------------------------- /src/styles/abstract/functions/_pxToRem.scss: -------------------------------------------------------------------------------- 1 | @use "sass:math" as math; 2 | @function pxToRem($value) { 3 | $remValue: calc($value * 1rem / 16); 4 | @return $remValue; 5 | } -------------------------------------------------------------------------------- /src/sdk/enums.ts: -------------------------------------------------------------------------------- 1 | // The enums correspond to the numbers of different Engines 2 | export enum Engine { 3 | Bun = 1, 4 | Deno = 2, 5 | Node = 3, 6 | Golang = 4, 7 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict", 3 | "include": [ 4 | ".astro/types.d.ts", 5 | "**/*" 6 | ], 7 | "exclude": [ 8 | "dist" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/styles/6-elements/_divider.scss: -------------------------------------------------------------------------------- 1 | @use "../abstract" as *; 2 | 3 | .divider { 4 | height: 1px; 5 | width: calc(100% + 2rem); 6 | background-color: hsl(var(--color-border)); 7 | } 8 | -------------------------------------------------------------------------------- /src/styles/_4-icons.scss: -------------------------------------------------------------------------------- 1 | html [class^="icon-"], 2 | html [class*=" icon-"] { 3 | font-size: var(--icon-size-medium); 4 | &::before { vertical-align:middle; } /* add for centering */ 5 | } -------------------------------------------------------------------------------- /src/styles/1-css-variables/_index.scss: -------------------------------------------------------------------------------- 1 | @forward "language"; 2 | @forward "common"; 3 | @forward "fonts"; 4 | @forward "colors"; 5 | @forward "sizes"; 6 | @forward "border-radius"; 7 | @forward "shadows"; -------------------------------------------------------------------------------- /src/styles/custom.scss: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap'); 2 | 3 | * { 4 | font-family: "Montserrat", sans-serif; 5 | } -------------------------------------------------------------------------------- /src/styles/6-elements/_logo.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .logo { 4 | flex-shrink: 0; /* if in container of flex can't shrink */ 5 | display: block; /* if on link element */ 6 | img { display:block; } 7 | } -------------------------------------------------------------------------------- /src/styles/abstract/variables/_devices.scss: -------------------------------------------------------------------------------- 1 | // Responsive Variables 2 | $break1: "(max-width:767.99px)"; 3 | $break2: "(min-width:768px) and (max-width:1198.99px)"; 4 | $break2open:"(min-width:768px)"; 5 | $break3open:"(min-width:1199px)"; -------------------------------------------------------------------------------- /src/styles/8-grids/_grid-300px-1fr.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .grid-300px-1fr { 4 | display: grid; 5 | gap: pxToRem(32); 6 | 7 | @media #{$break3open} { 8 | grid-template-columns: pxToRem(300) 1fr; 9 | } 10 | } -------------------------------------------------------------------------------- /license/README.MD: -------------------------------------------------------------------------------- 1 | LICENSE 2 | 3 | - [NON-COMMERCIAL](./NON-COMMERCIAL.MD) - For most independant users. 4 | - [COMMERCIAL](./COMMERCIAL.MD) - For business or people wanting to use this software on their own platform or those who want to modify and monetize it. 5 | 6 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "command": "./node_modules/.bin/astro dev", 6 | "name": "Development server", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /src/sdk/abstract.ts: -------------------------------------------------------------------------------- 1 | import Crabshell from "."; 2 | 3 | const can = new Crabshell(`127.0.0.1:50051`) 4 | 5 | 6 | class Abstraction { 7 | async getApplicationList() { 8 | return (await can.fetch_all_raw()) 9 | } 10 | } 11 | 12 | export default new Abstraction() -------------------------------------------------------------------------------- /src/styles/1-css-variables/_language.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | --transform-direction: 1; 3 | --start-direction: left; 4 | --end-direction: right; 5 | 6 | &[dir="rtl"] { 7 | --transform-direction: -1; 8 | --start-direction: right; 9 | --end-direction: left; 10 | } 11 | } -------------------------------------------------------------------------------- /src/styles/1-css-variables/_border-radius.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | :root { 3 | --border-radius-xsmall: #{pxToRem(4)}; 4 | --border-radius-small: #{pxToRem(8)}; 5 | --border-radius-medium: #{pxToRem(16)}; 6 | --border-radius-large: #{pxToRem(24)}; 7 | --border-radius-circular: 50%; 8 | } -------------------------------------------------------------------------------- /src/styles/8-grids/_grid-1-2.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .grid-1-2 { 4 | display: grid; 5 | row-gap: pxToRem(32); 6 | 7 | @media #{$break2open} { 8 | grid-template-columns: 1fr 1.5fr; 9 | column-gap: pxToRem(100); 10 | 11 | &-col { 12 | &-1 {} 13 | &-2 {} 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/styles/6-elements/form/_notification.scss: -------------------------------------------------------------------------------- 1 | @use '../../abstract' as *; 2 | .notification { 3 | inline-size:pxToRem(6); block-size:pxToRem(6); box-sizing:content-box; 4 | background-color:hsl(var(--color-primary-100)); 5 | border:solid pxToRem(2) hsl(var(--p-body-bg-color)); 6 | border-radius:var(--border-radius-circular); 7 | } -------------------------------------------------------------------------------- /src/styles/6-elements/_link.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .link { 3 | cursor:pointer; text-decoration:underline; 4 | > * { vertical-align:middle; } 5 | &.is-5px-offset { text-underline-offset:pxToRem(5); } 6 | &.is-add-sep { 7 | > *:nth-child(n + 2)::before { content:"|"; margin-inline:pxToRem(4); font-size:pxToRem(10); } 8 | } 9 | } -------------------------------------------------------------------------------- /src/styles/5-animations/_rotate.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | /* usage class */ 3 | .animation-rotate { 4 | animation: rotate 1s infinite linear; 5 | @media (prefers-reduced-motion) { animation-duration:0s; } 6 | } 7 | 8 | /** Bounce Animation **/ 9 | @keyframes rotate { 10 | 100% { 11 | transform: rotate(360deg); 12 | } 13 | } -------------------------------------------------------------------------------- /src/styles/8-grids/_grid-2-1.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .grid-2-1 { 4 | --p-gap: #{pxToRem(16)}; 5 | --p-gap-mobile: var(--p-gap); 6 | display: grid; 7 | gap: var(--p-gap); 8 | 9 | @media #{$break1} { 10 | gap: var(--p-gap-mobile); 11 | } 12 | @media #{$break2open} { 13 | grid-template-columns: 2fr 1fr; 14 | } 15 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | 4 | # generated types 5 | .astro/ 6 | 7 | # dependencies 8 | node_modules/ 9 | 10 | # logs 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | 23 | # jetbrains setting folder 24 | .idea/ 25 | -------------------------------------------------------------------------------- /src/styles/abstract/mixins/_trim.scss: -------------------------------------------------------------------------------- 1 | @mixin trim($numLines: null){ 2 | @if $numLines != null { 3 | display:-webkit-box; 4 | -webkit-line-clamp:$numLines; 5 | -webkit-box-orient:vertical; 6 | overflow:hidden; 7 | word-break:break-all; 8 | } 9 | @else{ 10 | text-overflow:ellipsis; 11 | white-space:nowrap; 12 | overflow:hidden; 13 | display:block; 14 | } 15 | } -------------------------------------------------------------------------------- /src/styles/8-grids/_inner-grid.scss: -------------------------------------------------------------------------------- 1 | /* from old layout */ 2 | @use '../abstract' as *; 3 | .inner-grid { 4 | display:flex; column-gap:pxToRem(40); row-gap:pxToRem(20); flex-wrap:wrap; 5 | 6 | &-main { flex-grow:1; flex-basis: pxToRem(580); } 7 | &-side {flex:1; flex-basis: pxToRem(320); } 8 | 9 | &-main, 10 | &-side { 11 | display:flex; flex-direction:column; gap:pxToRem(20); 12 | } 13 | } -------------------------------------------------------------------------------- /src/styles/6-elements/form/_index.scss: -------------------------------------------------------------------------------- 1 | @forward "label"; 2 | @forward "optional"; 3 | @forward "helper"; 4 | @forward "placeholder"; 5 | @forward "text-inputs"; 6 | @forward "password-meter"; 7 | @forward "radio-and-checkbox"; 8 | @forward "switch"; 9 | @forward "notification"; 10 | @forward "pulse-notification"; 11 | @forward "interactive-text-output"; 12 | 13 | /* form layout */ 14 | @forward "form"; 15 | -------------------------------------------------------------------------------- /src/sdk/proto/database.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package database; 3 | 4 | service Application { 5 | rpc Start (GetAllUsersRequest) returns (GetAllUsersResponse); 6 | } 7 | 8 | message GetAllUsersRequest { 9 | string id = 1; 10 | } 11 | 12 | message UserInfo { 13 | string username = 1; 14 | string password = 2; 15 | } 16 | 17 | message GetAllUsersResponse { 18 | repeated UserInfo data = 1; 19 | } 20 | -------------------------------------------------------------------------------- /src/styles/6-elements/_index.scss: -------------------------------------------------------------------------------- 1 | @forward "link"; 2 | @forward "button"; 3 | @forward "kbd"; 4 | @forward "image-item"; 5 | @forward "form"; 6 | @forward "tooltip"; 7 | @forward "tag"; 8 | @forward "inline-tag"; 9 | @forward "logo"; 10 | @forward "avatar"; 11 | @forward "card"; 12 | @forward "table"; 13 | @forward "container"; 14 | @forward "box"; 15 | @forward "loader"; 16 | @forward "inline-code"; 17 | @forward "divider"; 18 | -------------------------------------------------------------------------------- /src/styles/8-grids/_index.scss: -------------------------------------------------------------------------------- 1 | @forward "grid-with-side"; 2 | @forward "grid-box"; 3 | @forward "grid-header"; 4 | @forward "grid-code"; 5 | @forward "grid-1-1"; 6 | @forward "grid-1-2"; 7 | @forward "grid-2-1"; 8 | @forward "grid-300px-1fr"; 9 | @forward "grid-dashboard-1s-2m-6l"; 10 | 11 | @forward "wizard"; 12 | @forward "wizard-secondary"; 13 | @forward "cover-frame"; 14 | 15 | /* old grid from old console */ 16 | @forward "inner-grid"; -------------------------------------------------------------------------------- /src/styles/5-animations/_bounce.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | /* usage class */ 3 | .animation-bounce { 4 | animation:bounce infinite 2s; 5 | @media (prefers-reduced-motion) { animation:none; } 6 | } 7 | 8 | /** Bounce Animation **/ 9 | @keyframes bounce { 10 | 0%, 20%, 50%, 80%, 100% { 11 | transform: translateY(pxToRem(0)); 12 | } 13 | 40% { 14 | transform: translateY(pxToRem(-15)); 15 | } 16 | 60% { 17 | transform: translateY(pxToRem(-7)); 18 | } 19 | } -------------------------------------------------------------------------------- /src/styles/2-resets/_index.scss: -------------------------------------------------------------------------------- 1 | @use 'sass:meta'; 2 | @layer normalize, the-new-css-reset, custom-css-reset, typography; 3 | 4 | @layer normalize { 5 | @include meta.load-css('normalize.css/normalize.css'); 6 | } 7 | @layer the-new-css-reset { 8 | @include meta.load-css('the-new-css-reset/css/reset.css'); 9 | } 10 | 11 | @layer custom-css-reset { 12 | @include meta.load-css('custom-css-reset'); 13 | } 14 | 15 | @layer typography { 16 | @include meta.load-css('typography'); 17 | } 18 | -------------------------------------------------------------------------------- /src/pages/404.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

404

9 |

10 | The page you were looking for, was not found. 11 |

12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /src/styles/6-elements/form/_helper.scss: -------------------------------------------------------------------------------- 1 | @use '../../abstract' as *; 2 | .helper { 3 | --p-text-color: var(--color-neutral-50); 4 | display:flex; 5 | font-size:var(--font-size-0); line-height:2; color:hsl(var(--p-text-color)); font-weight:400; 6 | 7 | [class*="icon"] { 8 | line-height:1.3; 9 | &::before { vertical-align:pxToRem(-3); } 10 | &:first-child { margin-inline-end:pxToRem(4); } 11 | } 12 | 13 | #{$theme-dark} &{ 14 | --p-text-color: var(--color-neutral-20); 15 | } 16 | } -------------------------------------------------------------------------------- /src/sdk/proto/broadcast.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package broadcast; 4 | 5 | // Define the message structure for the broadcast 6 | message BroadcastMessage { 7 | string message = 1; 8 | } 9 | 10 | // Empty request if the server streams continuously without any request input 11 | message Empty {} 12 | 13 | // The broadcast service definition 14 | service BroadcastService { 15 | // Server-side streaming to send multiple messages 16 | rpc Subscribe (Empty) returns (stream BroadcastMessage); 17 | } 18 | -------------------------------------------------------------------------------- /src/styles/6-elements/form/_label.scss: -------------------------------------------------------------------------------- 1 | @use '../../abstract' as *; 2 | .label { 3 | --p-label-text-color: var(--color-neutral-80); 4 | 5 | color: hsl(var(--p-label-text-color)); 6 | display: inline-block; 7 | cursor: pointer; 8 | line-height: 1.5; 9 | margin-bottom: pxToRem(4); 10 | font-size: var(--font-size-0); 11 | 12 | &:where(.is-required)::after { content:"*"; color:hsl(var(--color-danger-100)); } 13 | 14 | #{$theme-dark} & { 15 | --p-label-text-color: var(--color-neutral-5); 16 | } 17 | } -------------------------------------------------------------------------------- /src/styles/8-grids/_grid-code.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .grid-code { 4 | display: grid; 5 | grid-template-columns: auto 1fr; 6 | grid-auto-rows: auto; 7 | column-gap: pxToRem(8); 8 | align-content: start; 9 | 10 | font-family: var(--code-font); 11 | 12 | counter-reset: lineNumbers; 13 | 14 | &-line-number { 15 | color: hsl(var(--color-neutral-50)); 16 | &::before { 17 | counter-increment: lineNumbers; 18 | content: counter(lineNumbers); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/sdk/proto/system.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package system; 3 | 4 | message Empty {} 5 | 6 | service SystemService { 7 | rpc GetSystemInfo (Empty) returns (stream SystemInfo); 8 | rpc GetResourceUsage (Empty) returns (stream Resources); 9 | } 10 | 11 | message Resources { 12 | int64 memory_used = 1; 13 | int64 disk_used = 2; 14 | int64 cpu_used = 3; 15 | } 16 | 17 | message SystemInfo { 18 | int64 total_memory = 1; 19 | int64 total_disk = 2; 20 | CpuInfo cpu = 3; 21 | } 22 | 23 | message CpuInfo { 24 | int64 speed = 1; 25 | } -------------------------------------------------------------------------------- /src/styles/6-elements/_inline-code.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .inline-code { 3 | --p-bg-color-inline-code: var(--color-neutral-10); 4 | --p-text-color-inline-code: var(--color-neutral-60); 5 | 6 | background-color: hsl(var(--p-bg-color-inline-code)); 7 | color: hsl(var(--p-text-color-inline-code)); 8 | border-radius: var(--border-radius-xsmall); 9 | 10 | padding: pxToRem(4); 11 | 12 | #{$theme-dark} & { 13 | --p-bg-color-inline-code: var(--color-neutral-100); 14 | --p-text-color-inline-code: var(--color-neutral-15); 15 | } 16 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-project", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "astro dev", 7 | "build": "astro build", 8 | "preview": "astro preview", 9 | "astro": "astro" 10 | }, 11 | "dependencies": { 12 | "@appwrite.io/pink": "^1.0.0", 13 | "@astrojs/node": "^9.1.3", 14 | "@astrojs/tailwind": "^6.0.2", 15 | "@tailwindcss/vite": "^4.1.3", 16 | "astro": "^5.6.1", 17 | "astro-icon": "^1.1.5", 18 | "tailwindcss": "^3.4.17" 19 | }, 20 | "devDependencies": { 21 | "sass-embedded": "^1.86.3" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/styles/1-css-variables/_sizes.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | :root { 3 | --container-size-small: #{pxToRem(320)}; 4 | --container-size-medium: #{pxToRem(496)}; 5 | --container-size-large: #{pxToRem(700)}; 6 | --container-size-xl: #{pxToRem(928)}; 7 | --container-size-xxl: #{pxToRem(1260)}; 8 | --container-size-xxxl: #{pxToRem(1394)}; 9 | 10 | /* icons */ 11 | --icon-size-small: #{pxToRem(16)}; 12 | --icon-size-medium: #{pxToRem(20)}; /* default */ 13 | --icon-size-large: #{pxToRem(24)}; 14 | --icon-size-extra-large: #{pxToRem(32)}; 15 | 16 | } -------------------------------------------------------------------------------- /src/styles/1-css-variables/_fonts.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | :root { 3 | --heading-font: 'Poppins', arial, sans-serif; 4 | --content-font: 'Inter', arial, sans-serif; 5 | --code-font: 'Source Code Pro', monospace; 6 | 7 | --font-size-00: #{pxToRem(12)}; 8 | --font-size-0: #{pxToRem(14)}; 9 | --font-size-1: #{pxToRem(16)}; 10 | --font-size-2: #{pxToRem(18)}; 11 | --font-size-3: #{pxToRem(20)}; 12 | --font-size-4: #{pxToRem(24)}; 13 | --font-size-5: #{pxToRem(28)}; 14 | --font-size-6: #{pxToRem(32)}; 15 | --font-size-7: #{pxToRem(36)}; 16 | --font-size-8: #{pxToRem(40)}; 17 | } -------------------------------------------------------------------------------- /src/styles/7-components/_main-footer.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .main-footer { 4 | display: flex; 5 | flex-wrap: wrap; 6 | padding-block: pxToRem(16); 7 | border-block-start: solid pxToRem(1) hsl(var(--color-border)); 8 | margin-inline: pxToRem(32); 9 | margin-block-start: pxToRem(32); 10 | font-size: var(--font-size-00); 11 | @media #{$break1}, #{$break2} { 12 | gap:pxToRem(16); 13 | &-start { margin-inline-end:auto; } 14 | } 15 | @media #{$break3open} { 16 | display: flex; 17 | flex-direction: row-reverse; 18 | justify-content: space-between; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/styles/7-components/_inline-links.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .inline-links { 3 | display: flex; 4 | align-items: baseline; 5 | font-size: pxToRem(14); 6 | 7 | &-item { 8 | padding-inline:pxToRem(20); 9 | &:where(:not(:last-child)) { border-inline-end:solid pxToRem(1) hsl(var(--color-border)); } 10 | } 11 | /* states */ 12 | &:where(.is-center) { justify-content:center; } 13 | 14 | &:where(.is-no-padding-first-and-last) { 15 | :where(.inline-links-item) { 16 | &:first-child { padding-inline-start:0; } 17 | &:last-child { padding-inline-end:0; } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/styles/8-grids/_grid-header.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .grid-header { 3 | gap: pxToRem(24); 4 | 5 | /* mobile */ 6 | @media #{$break1} { 7 | display:grid; grid-template-columns:auto auto; 8 | grid-template-areas: "col-1 col-2" 9 | "col-3 col-4"; 10 | &-col { 11 | &-1 { grid-area:col-1; } 12 | &-2 { grid-area:col-2; justify-self:end; } 13 | &-3 { grid-area:col-3; justify-self:start; } 14 | &-4 { grid-area:col-4; justify-self:end; } 15 | } 16 | } 17 | /* tablet & desktop */ 18 | @media #{$break2}, #{$break3open} { 19 | display:flex; justify-content:space-between; 20 | } 21 | } -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | // tailwind.config.js 2 | 3 | module.exports = { 4 | content: ["./src/**/*.{astro,html,js,jsx,ts,tsx}"], 5 | theme: { 6 | darkMode: 'class', 7 | extend: { 8 | colors: { 9 | neutral: { 10 | 10: "hsl(var(--color-neutral-10))", 11 | 15: "hsl(var(--color-neutral-15))", 12 | 20: "hsl(var(--color-neutral-20))", 13 | 85: "hsl(var(--color-neutral-85))", 14 | 90: "hsl(var(--color-neutral-90))", 15 | }, 16 | primary: { 17 | 100: "hsl(var(--color-primary-100))", 18 | }, 19 | // Add more color categories if needed 20 | }, 21 | }, 22 | }, 23 | plugins: [ 24 | 25 | ], 26 | }; 27 | -------------------------------------------------------------------------------- /src/styles/8-grids/_cover-frame.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract/index' as *; 2 | 3 | .cover-frame { 4 | --p-cover-frame-bg-header: var(--transparent); 5 | 6 | display:flex; flex-direction:column; 7 | block-size:100vh; block-size:100lvh; 8 | &-header { 9 | padding-inline:pxToRem(32); padding-block:pxToRem(20); border-block-end:solid pxToRem(1) hsl(var(--color-border)); 10 | background-color: hsl(var(--p-cover-frame-bg-header)); 11 | } 12 | &-content { 13 | flex:1; padding:pxToRem(32); overflow:hidden; 14 | } 15 | 16 | /* state */ 17 | &.is-color-header { 18 | --p-cover-frame-bg-header:var(--color-neutral-0); 19 | #{$theme-dark} & { --p-cover-frame-bg-header:var(--color-neutral-500); } 20 | } 21 | } -------------------------------------------------------------------------------- /src/styles/2-resets/_custom-css-reset.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | /** custom reset **/ 3 | :where(dialog:modal) { all:revert; } 4 | 5 | img[src=""] { 6 | visibility: hidden; 7 | } 8 | 9 | button { 10 | cursor: pointer; 11 | } 12 | 13 | pre { 14 | margin-block: 0; 15 | } 16 | 17 | details summary::-webkit-details-marker { 18 | display:none; 19 | } 20 | 21 | summary::-webkit-details-marker { display:none!important; } 22 | 23 | input::-webkit-datetime-edit { line-height:1; padding:0; margin-bottom:-2px; } 24 | 25 | 26 | #{$theme-dark} { 27 | input[type="date"]::-webkit-calendar-picker-indicator { filter:invert(0.8); } 28 | input[type="time"]::-webkit-calendar-picker-indicator { filter:invert(0.8); } 29 | } 30 | -------------------------------------------------------------------------------- /src/styles/8-grids/_grid-box.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .grid-box { 3 | $grid-gap: pxToRem(24); 4 | --p-grid-gap: var(--grid-gap, #{$grid-gap}); 5 | 6 | $grid-item-size: pxToRem(210); 7 | --p-grid-item-size: var(--grid-item-size, #{$grid-item-size}); 8 | 9 | $grid-item-size-small-screens: pxToRem(210); 10 | --p-grid-item-size-small-screens: var(--grid-item-size-small-screens, #{$grid-item-size-small-screens}); 11 | 12 | display: grid; 13 | grid-template-columns: repeat(auto-fill, minmax(var(--p-grid-item-size), 1fr)); 14 | grid-auto-rows: 1fr; 15 | gap: var(--p-grid-gap); 16 | flex-shrink: 0; 17 | 18 | @media #{$break1} { 19 | --p-grid-item-size: var(--p-grid-item-size-small-screens); 20 | } 21 | } -------------------------------------------------------------------------------- /src/styles/_index.scss: -------------------------------------------------------------------------------- 1 | @use 'sass:meta'; 2 | 3 | @layer css-variables, resets, icons, animations, elements, components, grids, utilities; 4 | 5 | @layer css-variables { 6 | @include meta.load-css('1-css-variables'); 7 | } 8 | @layer resets { 9 | @include meta.load-css('2-resets'); 10 | } 11 | @layer icons { 12 | @include meta.load-css('4-icons'); 13 | } 14 | @layer animations { 15 | @include meta.load-css('5-animations'); 16 | } 17 | @layer elements { 18 | @include meta.load-css('6-elements'); 19 | } 20 | @layer components { 21 | @include meta.load-css('7-components'); 22 | } 23 | @layer grids { 24 | @include meta.load-css('8-grids'); 25 | } 26 | @layer utilities { 27 | @include meta.load-css('9-utilities'); 28 | } 29 | -------------------------------------------------------------------------------- /src/styles/8-grids/_grid-dashboard-1s-2m-6l.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .grid-dashboard-1s-2m-6l { 4 | /* all screens */ 5 | display: grid; 6 | gap: pxToRem(24); 7 | 8 | /* medium screen */ 9 | @media #{$break2} { 10 | grid-template-columns: repeat(2, 1fr); 11 | .is-2-columns-medium-screen { grid-column:span 2; } 12 | } 13 | 14 | /* large screen */ 15 | @media #{$break3open} { 16 | grid-template-columns: repeat(6, 1fr); 17 | .is-2-columns-large-screen { grid-column:span 2; } 18 | .is-3-columns-large-screen { grid-column:span 3; } 19 | .is-location-row-2-end-large-screen { grid-row-start:2; grid-column-end:-1; } 20 | .is-2-rows-large-screen { grid-row-end:span 2; } 21 | } 22 | } -------------------------------------------------------------------------------- /src/sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@grpc/grpc-js": "^1.12.2", 4 | "@grpc/proto-loader": "^0.7.13", 5 | "@improbable-eng/grpc-web": "^0.15.0", 6 | "browser-headers": "^0.4.1", 7 | "express": "^4.21.1", 8 | "google-protobuf": "^3.21.4", 9 | "grpc-web": "^1.5.0", 10 | "protobufjs-cli": "^1.1.3" 11 | }, 12 | "devDependencies": { 13 | "@types/bun": "latest", 14 | "@types/express": "^5.0.0", 15 | "@types/node": "^22.13.5" 16 | }, 17 | "name": "client", 18 | "module": "index.ts", 19 | "type": "module", 20 | "peerDependencies": { 21 | "typescript": "^5.0.0" 22 | }, 23 | "pnpm": { 24 | "ignoredBuiltDependencies": [ 25 | "protobufjs" 26 | ] 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/styles/6-elements/form/_placeholder.scss: -------------------------------------------------------------------------------- 1 | @use '../../abstract' as *; 2 | 3 | ::placeholder, 4 | [contentEditable="true"] { 5 | --p-placeholder-color: var(--color-neutral-20); 6 | --p-placeholder-color-disabled: var(--color-neutral-20); 7 | 8 | #{$theme-dark} & { 9 | --p-placeholder-color: var(--color-neutral-60); 10 | } 11 | } 12 | 13 | ::placeholder { 14 | color: hsl(var(--p-placeholder-color)); 15 | } 16 | 17 | :disabled::placeholder { 18 | color: hsl(var(--p-placeholder-color-disabled)); 19 | #{$theme-dark} & { 20 | --p-placeholder-color: var(--color-neutral-70); 21 | --p-placeholder-color-disabled: var(--color-neutral-70); 22 | } 23 | } 24 | 25 | [contentEditable="true"] { 26 | &::before { color:hsl(var(--p-placeholder-color)); } 27 | } -------------------------------------------------------------------------------- /src/styles/7-components/_breadcrumbs.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .breadcrumbs { 4 | --p-text-color: var(--color-neutral-50); 5 | --p-text-color-current: var(--color-neutral-80); 6 | 7 | color: hsl(var(--p-text-color)); 8 | -webkit-user-select:none; user-select:none; 9 | 10 | &-list { display:flex; } 11 | &-item { 12 | @include trim; flex-shrink:0; text-transform:capitalize; 13 | > * { padding-inline:pxToRem(16); } 14 | &::before { content:"/"; color:hsl(var(--p-text-color)); } 15 | &:last-child { 16 | color: hsl(var(--p-text-color-current)); flex-shrink:1; 17 | } 18 | } 19 | 20 | #{$theme-dark} & { 21 | --p-text-color: var(--color-neutral-20); 22 | --p-text-color-current: var(--color-neutral-5); 23 | } 24 | } -------------------------------------------------------------------------------- /public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /src/styles/1-css-variables/_shadows.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | :root { 4 | --shadow-color: var(--color-neutral-80); 5 | 6 | --shadow-small: #{pxToRem(0) pxToRem(16) pxToRem(32) hsl(var(--shadow-color) / 0.02)}; 7 | --shadow-large: #{pxToRem(0) pxToRem(16) pxToRem(32) hsl(var(--shadow-color) / 0.04)}; 8 | 9 | /* focus state shadow */ 10 | $focus: 0 0 0 pxToRem(1) hsl(var(--color-information-100)), 0 0 0 pxToRem(4) hsl(var(--color-information-100) / 0.25); 11 | --focus-box-shadow: #{$focus}; 12 | 13 | #{$theme-dark} { 14 | --shadow-color: var(--color-neutral-105); 15 | 16 | --shadow-small: #{pxToRem(0) pxToRem(16) pxToRem(32) hsl(var(--shadow-color) / 0.5)}; 17 | --shadow-large: #{pxToRem(0) pxToRem(16) pxToRem(32) hsl(var(--shadow-color) / 1)}; 18 | } 19 | } -------------------------------------------------------------------------------- /src/sdk/events.ts: -------------------------------------------------------------------------------- 1 | import EventEmitter from 'events'; 2 | 3 | export enum EventTypes { 4 | STD_OUT = "std_out", 5 | STD_ERR = "std_err", 6 | } 7 | 8 | export default class CancalaEvent { 9 | private emitter: EventEmitter; 10 | 11 | constructor() { 12 | this.emitter = new EventEmitter(); 13 | } 14 | 15 | onOut(callback: (data: T) => void) { 16 | this.emitter.on(EventTypes.STD_OUT, callback); 17 | } 18 | 19 | offOut(callback: (data: T) => void) { 20 | this.emitter.off(EventTypes.STD_OUT, callback); 21 | } 22 | 23 | onceOut(callback: (data: T) => void) { 24 | this.emitter.once(EventTypes.STD_OUT, callback); 25 | } 26 | 27 | emitOut(data: T) { 28 | this.emitter.emit(EventTypes.STD_OUT, data); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/styles/6-elements/_kbd.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .kbd { 4 | --p-kbd-text-color: var(--color-neutral-60); 5 | --p-kbd-bg-color: var(--color-neutral-5); 6 | --p-kbd-border-color: var(--color-neutral-15); 7 | 8 | color: hsl(var(--p-kbd-text-color)); 9 | background-color: hsl(var(--p-kbd-bg-color)); 10 | border: solid pxToRem(1) hsl(var(--p-kbd-border-color)); 11 | 12 | display:inline-flex; justify-content:center; align-items:center; 13 | min-inline-size:pxToRem(24); block-size:pxToRem(24); 14 | border-radius:var(--border-radius-xsmall); flex-shrink:0; 15 | -webkit-user-select:none; user-select:none; 16 | 17 | #{$theme-dark} & { 18 | --p-kbd-text-color: var(--color-neutral-5); 19 | --p-kbd-bg-color: var(--color-neutral-90); 20 | --p-kbd-border-color: var(--color-neutral-80); 21 | } 22 | } -------------------------------------------------------------------------------- /src/styles/7-components/_status.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .status { 4 | --p-status-color: var(--color-neutral-50); 5 | 6 | display: flex; 7 | align-items: baseline; 8 | gap: pxToRem(8); 9 | user-select: none; 10 | &-icon { 11 | inline-size:pxToRem(12); block-size:pxToRem(12); border-radius:var(--border-radius-circular); 12 | background-color:hsl(var(--p-status-color)); 13 | } 14 | 15 | /* Status */ 16 | &.is-offline { --p-status-color:var(--color-neutral-50); } 17 | &.is-waiting { --p-status-color:var(--color-warning-50); } 18 | &.is-pending { --p-status-color:var(--color-warning-100); } 19 | &.is-failed { --p-status-color:var(--color-danger-100); } 20 | &.is-complete { --p-status-color:var(--color-success-100); } 21 | &.is-processing { --p-status-color:var(--color-information-100);} 22 | } -------------------------------------------------------------------------------- /src/styles/7-components/_pagination.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .pagination { 3 | $button-size: pxToRem(32); 4 | --button-size: #{$button-size}; 5 | 6 | display:flex; gap:pxToRem(20); 7 | 8 | &-list { 9 | display:flex; gap:pxToRem(8); 10 | } 11 | .button { 12 | flex-shrink:0; padding-inline:pxToRem(12); 13 | [class*="icon"] { 14 | transform: scaleX(var(--transform-direction)); 15 | &::before { vertical-align:middle; } 16 | } 17 | 18 | /* adjust color from default button */ 19 | &:where(:not(.is-text)) { 20 | --p-text-color-disabled: var(--color-neutral-90); 21 | #{$theme-dark} & { 22 | --p-text-color-disabled: var(--color-neutral-20); 23 | } 24 | } 25 | } 26 | 27 | /* states */ 28 | &.is-center { justify-content:center; } 29 | &.is-end { justify-content:flex-end; } 30 | } -------------------------------------------------------------------------------- /src/styles/6-elements/form/_pulse-notification.scss: -------------------------------------------------------------------------------- 1 | @use '../../abstract' as *; 2 | 3 | .pulse-notification { 4 | --p-pulse-color: var(--color-primary-200); 5 | box-sizing: content-box; 6 | inline-size: pxToRem(8); 7 | block-size: pxToRem(8); 8 | background-color: hsl(var(--p-pulse-color)); 9 | border-radius: 50%; 10 | position: relative; 11 | &::before { 12 | content:''; display:block; 13 | position:absolute; inset:pxToRem(-1); 14 | border-radius:50%; border:pxToRem(0.25) double hsl(var(--p-pulse-color)); 15 | animation: pulse 1s ease infinite; 16 | @media (prefers-reduced-motion) { animation:none; } 17 | } 18 | } 19 | 20 | @keyframes pulse { 21 | 0% { 22 | transform: scale(1); 23 | opacity: 1; 24 | } 25 | 60% { 26 | transform: scale(1.2); 27 | opacity: 0.6; 28 | } 29 | 100% { 30 | transform: scale(1.3); 31 | opacity: 0.3; 32 | } 33 | } -------------------------------------------------------------------------------- /src/styles/7-components/_index.scss: -------------------------------------------------------------------------------- 1 | @forward "alert"; 2 | @forward "alert-sticky"; 3 | @forward "action-bar"; 4 | @forward "list"; 5 | @forward "collapsible"; 6 | @forward "tabs"; 7 | @forward "secondary-tabs"; 8 | @forward "modal"; 9 | @forward "drop"; 10 | @forward "inline-links"; 11 | @forward "upload-image"; 12 | @forward "status"; 13 | @forward "upload-box"; 14 | @forward "upload-file-box"; 15 | @forward "file-preview"; 16 | @forward "grid-item-1"; 17 | @forward "pagination"; 18 | @forward "steps"; 19 | @forward "buttons-list"; 20 | @forward "toggle-button"; 21 | @forward "clickable-list"; 22 | @forward "progress-bar"; 23 | @forward "top-cover"; 24 | 25 | @forward "code-panel"; 26 | @forward "tab-text-ediror"; 27 | 28 | @forward "top-banner"; 29 | 30 | /* main parts */ 31 | @forward "main-header"; 32 | @forward "breadcrumbs"; 33 | @forward "user-profile"; 34 | @forward "side-nav"; 35 | @forward "main-footer"; 36 | -------------------------------------------------------------------------------- /astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'astro/config'; 2 | import tailwind from '@astrojs/tailwind'; 3 | import icon from 'astro-icon'; 4 | import node from '@astrojs/node'; // ✅ Node adapter 5 | 6 | export default defineConfig({ 7 | integrations: [ 8 | tailwind({ 9 | config: { 10 | // Enable future Tailwind optimizations 11 | purge: ['./src/**/*.{astro,js,ts,jsx,tsx,vue,svelte}'], 12 | darkMode: 'class', 13 | }, 14 | }), 15 | icon(), 16 | ], 17 | output: 'server', // ✅ Needed for SSR with node 18 | adapter: node({ 19 | mode: 'standalone', // ✅ Bundles everything into a single Node app 20 | }), 21 | build: { 22 | format: 'file', // ✅ Outputs .mjs files, best for deployment 23 | inlineStylesheets: 'auto', // inline critical CSS automatically 24 | }, 25 | compressHTML: true, // ✅ Minifies HTML output 26 | }); 27 | -------------------------------------------------------------------------------- /src/styles/7-components/_grid-item-1.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .grid-item-1 { 3 | --small-title-color: var(--color-neutral-20); 4 | 5 | display: grid; 6 | grid-template-areas: "start-start start-end" 7 | "end-start end-end"; 8 | grid-template-columns: 1fr auto; 9 | grid-template-rows: auto 1fr; 10 | column-gap: pxToRem(16); 11 | row-gap: pxToRem(48); 12 | 13 | block-size: 100%; 14 | 15 | &-start-start { grid-area:start-start; } 16 | &-start-end { grid-area:start-end; } 17 | &-end-start { grid-area:end-start; justify-content:end; align-self:end; } 18 | &-end-end { grid-area:end-end; display:flex; justify-content:end; align-items:end; } 19 | 20 | /* specific styles */ 21 | .eyebrow-heading-3 { color:hsl(var(--small-title-color)); } 22 | .icons { 23 | line-height: 1; 24 | [class*="icon"]::before { vertical-align:sub; } 25 | } 26 | } -------------------------------------------------------------------------------- /src/styles/abstract/mixins/_break-word.scss: -------------------------------------------------------------------------------- 1 | @mixin break-word { 2 | /* These are technically the same, but use both */ 3 | overflow-wrap: break-word; 4 | word-wrap: break-word; 5 | 6 | -ms-word-break: break-all; 7 | /* This is the dangerous one in WebKit, as it breaks things wherever */ 8 | word-break: break-all; 9 | /* Instead use this non-standard one: */ 10 | word-break: break-word; 11 | 12 | /* Adds a hyphen where the word breaks, if supported (No Blink) */ 13 | -ms-hyphens: auto; 14 | -moz-hyphens: auto; 15 | -webkit-hyphens: auto; 16 | hyphens: auto; 17 | } 18 | 19 | @mixin break-all { 20 | /* These are technically the same, but use both */ 21 | overflow-wrap: break-all; 22 | word-wrap: break-all; 23 | 24 | -ms-word-break: break-all; 25 | word-break: break-all; 26 | 27 | /* Adds a hyphen where the word breaks, if supported (No Blink) */ 28 | -ms-hyphens: auto; 29 | -moz-hyphens: auto; 30 | -webkit-hyphens: auto; 31 | hyphens: auto; 32 | } 33 | -------------------------------------------------------------------------------- /src/styles/7-components/_buttons-list.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .buttons-list { 4 | display: flex; 5 | --p-button-list-border-color: var(--color-neutral-15); 6 | &-item { 7 | position: relative; 8 | &:nth-child(n + 2) { 9 | border-inline-start: solid pxToRem(1) transparent; 10 | &::before { 11 | content:""; display:block; 12 | position:absolute; inset-inline-start:0; inset-block:0; margin-block:auto; 13 | inline-size:pxToRem(1); block-size:75%; background-color:hsl(var(--p-button-list-border-color)); 14 | } 15 | } 16 | } 17 | &.is-with-padding { 18 | .buttons-list-item { 19 | padding-inline: pxToRem(12); 20 | &:first-child { padding-inline-start:0; } 21 | &:last-child { padding-inline-end:0; } 22 | } 23 | } 24 | 25 | #{$theme-dark} & { 26 | --p-button-list-border-color: var(--color-neutral-80); 27 | } 28 | } 29 | 30 | 31 | /* TODO: similar inline links */ 32 | /* maybe new name interactive list */ -------------------------------------------------------------------------------- /src/styles/6-elements/_container.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .container { 3 | --p-container-max-size: var(--container-max-size, var(--container-size-xxl)); 4 | 5 | $padding-block:pxToRem(20); 6 | --p-container-padding-block: var(--container-padding-block, #{$padding-block}); 7 | 8 | inline-size: 100%; 9 | padding-inline: var(--p-container-padding-inline); 10 | padding-block: var(--p-container-padding-block); 11 | margin-inline: auto; 12 | max-inline-size: var(--p-container-max-size); 13 | &.is-size-xl { --p-container-max-size:var(--container-size-xl); } 14 | @media #{$break1} { $padding-inline:pxToRem(16); --p-container-padding-inline:#{$padding-inline}; } 15 | @media #{$break2} { $padding-inline:pxToRem(30); --p-container-padding-inline:#{$padding-inline}; } 16 | @media #{$break3open} { $padding-inline:pxToRem(50); --p-container-padding-inline:#{$padding-inline}; } 17 | } 18 | 19 | :where(.common-section) { 20 | &:where(:nth-child(n + 2)) { margin-block-start:pxToRem(24); } 21 | } -------------------------------------------------------------------------------- /src/styles/7-components/_top-cover.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .top-cover { 3 | --p-cover-bg-color: var(--color-neutral-0); 4 | --p-cover-border-color: var(--color-border); 5 | 6 | background-color: hsl(var(--p-cover-bg-color)); 7 | display: flex; 8 | flex-direction: column; 9 | min-block-size: pxToRem(186); 10 | border-block-end: solid pxToRem(1) hsl(var(--p-cover-border-color)); 11 | 12 | :where(.container) { 13 | flex:1; display:flex; flex-direction:column; 14 | .tabs{ margin-block-start:auto; margin-block-end:calc(var(--p-container-padding-block) * -1); } 15 | } 16 | @media #{$break3open} { 17 | [class*="heading-level-"] { 18 | position:relative; 19 | .button { 20 | position:absolute; inset-inline-start:0; 21 | transform: translateX( calc(-100% * var(--transform-direction)) ) 22 | scaleX(var(--transform-direction)); 23 | } 24 | } 25 | } 26 | 27 | 28 | 29 | #{$theme-dark} & { 30 | --p-cover-bg-color: var(--color-neutral-100); 31 | } 32 | } -------------------------------------------------------------------------------- /src/styles/6-elements/form/_form.scss: -------------------------------------------------------------------------------- 1 | @use '../../abstract' as *; 2 | .form { 3 | display:flex; flex-direction:column; 4 | &-header { 5 | display: grid; 6 | gap: pxToRem(16); 7 | padding-block-end: pxToRem(32); 8 | border-block-end: solid pxToRem(1) hsl(var(--color-border)); 9 | margin-block-end: pxToRem(32); 10 | :where([class*=heading-]) { margin-block:0; } 11 | } 12 | &-content { 13 | display:flex; flex-direction:column; gap:pxToRem(16); padding-block-end:pxToRem(32); 14 | } 15 | &-footer { 16 | padding-block:pxToRem(32); margin-block-start:pxToRem(32); 17 | border-block-start:solid pxToRem(1) hsl(var(--color-border)); 18 | } 19 | &-list { 20 | $gap: pxToRem(24); 21 | --p-form-list-gap:var(--form-list-gap, #{$gap}); 22 | display:grid; gap:var(--p-form-list-gap); 23 | 24 | &.is-multiple { grid-template-columns: repeat(auto-fit, minmax(pxToRem(180), 1fr)); } 25 | } 26 | &-item { 27 | &.is-multiple { display:flex; gap:pxToRem(8); } 28 | &.is-span-2 { grid-column:span 2;} 29 | &-part { } 30 | } 31 | } -------------------------------------------------------------------------------- /src/styles/6-elements/form/_password-meter.scss: -------------------------------------------------------------------------------- 1 | @use '../../abstract' as *; 2 | 3 | .password-meter { 4 | position:absolute; z-index:2; bottom:pxToRem(4); inset-inline:pxToRem(8); 5 | width:0%; height:pxToRem(2); max-width:#{calc(100% - pxToRem(16))}; background:none; 6 | transition:var(--transition); 7 | 8 | &::-webkit-meter-optimum-value { background-image:none; } /* Safari */ 9 | &::-webkit-meter-bar { background:none; } /* Safari */ 10 | &::-moz-meter-bar { background:none; } /* FireFox */ 11 | &.is-weak { 12 | background: hsl(var(--color-danger-100)); width:33.33%; 13 | &::-webkit-meter-optimum-value { background-color:hsl(var(--color-danger-100)); } /* Safari */ 14 | } 15 | &.is-medium { 16 | background: hsl(var(--color-warning-100)); width:66.66%; 17 | &::-webkit-meter-optimum-value { background-color:hsl(var(--color-warning-100)); } /* Safari */ 18 | } 19 | &.is-strong { 20 | background: hsl(var(--color-success-100)); width:100%; 21 | &::-webkit-meter-optimum-value { background-color:hsl(var(--color-success-100)); } /* Safari */ 22 | } 23 | } -------------------------------------------------------------------------------- /src/styles/7-components/_tab-text-ediror.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .tab-text-editor { 4 | --p-tab-text-editor-bg-color: var(--color-neutral-0); 5 | 6 | background-color:hsl(var(--p-tab-text-editor-bg-color)); 7 | border:solid pxToRem(1) hsl(var(--color-border)); border-radius:var(--border-radius-small); 8 | 9 | &-nav { padding:pxToRem(8); border-block-end:solid pxToRem(1) hsl(var(--color-border)); } 10 | &-content-box { position:relative; } 11 | &-content { padding:pxToRem(12); block-size:pxToRem(200); overflow:auto; border-width:0; font-family:var(--code-font); } 12 | &-options { 13 | opacity:0; transition:var(--transition); 14 | padding-inline-end:pxToRem(8); padding-block-end:pxToRem(8); 15 | position:absolute; inset-inline-end:0; inset-block-end:0; 16 | background: linear-gradient(315deg, hsl(var(--p-tab-text-editor-bg-color)) 35%, hsl(var(--p-tab-text-editor-bg-color) / 0) 100%); 17 | > * {filter:none; } 18 | } 19 | &:where(:focus-within, :hover, :focus) { 20 | .tab-text-editor-options { opacity:1; } 21 | } 22 | 23 | #{$theme-dark} & { 24 | --p-tab-text-editor-bg-color: var(--color-neutral-100); 25 | } 26 | } -------------------------------------------------------------------------------- /src/styles/7-components/_code-panel.scss: -------------------------------------------------------------------------------- 1 | @use "../abstract" as *; 2 | 3 | .code-panel { 4 | --p-code-panel-header: var(--color-neutral-5); 5 | --p-code-panel-border-color: var(--color-neutral-15); 6 | --p-code-panel-content: var(--color-neutral-0); 7 | //--p-code-panel-text-color: var(--color-neutral-120); 8 | 9 | display:flex; flex-direction:column; block-size:100%; flex-shrink:0; overflow:hidden; 10 | border: solid pxToRem(1) hsl(var(--p-code-panel-border-color)); 11 | border-radius: var(--border-radius-xsmall); 12 | //color: hsl(var(--p-code-panel-text-color)); 13 | &-header { 14 | display:flex; padding:pxToRem(16); 15 | background-color: hsl(var(--p-code-panel-header)); 16 | border-block-end: solid pxToRem(1) hsl(var(--p-code-panel-border-color)); 17 | } 18 | &-content { 19 | flex:1; padding:pxToRem(24); overflow:auto; 20 | background-color: hsl(var(--p-code-panel-content)); 21 | } 22 | #{$theme-dark} & { 23 | --p-code-panel-header: var(--color-neutral-100); 24 | --p-code-panel-border-color: var(--color-neutral-85); 25 | --p-code-panel-content: var(--color-neutral-200); 26 | --p-code-panel-text-color: var(--color-neutral-5); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/styles/7-components/_action-bar.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .action-bar { 3 | --p-action-bar-bg-color: var(--color-neutral-0); 4 | --p-action-bar-border-color: var(--color-neutral-0); 5 | --p-action-bar-box-shadow: 0 #{pxToRem(6)} #{pxToRem(16)} hsl(var(--color-neutral-80) / 0.14); 6 | 7 | display:flex; gap:pxToRem(8); justify-content:space-between; align-items:baseline; 8 | inline-size:pxToRem(312); padding-inline:pxToRem(12); padding-block:pxToRem(8); 9 | 10 | background-color: hsl(var(--p-action-bar-bg-color)); 11 | border: solid pxToRem(1) hsl(var(--p-action-bar-border-color)); 12 | border-radius: var(--border-radius-small); 13 | box-shadow: var(--p-action-bar-box-shadow); /* isn't standard box shadow */ 14 | transition: var(--transition); 15 | 16 | /* tablet & desktop */ 17 | @media #{$break2open} { inline-size:pxToRem(500); padding-inline:pxToRem(16); padding-block:pxToRem(12); } 18 | 19 | #{$theme-dark} & { 20 | --p-action-bar-bg-color: var(--color-neutral-90); 21 | --p-action-bar-border-color: var(--color-neutral-85); 22 | --p-action-bar-box-shadow: 0 #{pxToRem(6)} #{pxToRem(16)} #{pxToRem(8)} hsl(var(--color-neutral-105)); 23 | } 24 | } -------------------------------------------------------------------------------- /src/styles/6-elements/_image-item.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | /* TODO: check if can be merged with Avatar */ 3 | .image-item { 4 | --p-image-item-bg-color: var(--color-neutral-5); 5 | --p-image-item-border-color: var(--color-neutral-10); 6 | 7 | $size-item: pxToRem(40); 8 | --p-image-item-full-size: #{$size-item}; 9 | 10 | $size-item-image: pxToRem(20); 11 | --p-image-item-size: #{$size-item-image}; 12 | 13 | display:grid; place-content:center; 14 | flex-shrink:0; /* in case it a child of flexbox */ 15 | inline-size:var(--p-image-item-full-size); block-size:var(--p-image-item-full-size); 16 | background-color:hsl(var(--p-image-item-bg-color)); border:solid pxToRem(1) hsl(var(--p-image-item-border-color)); 17 | border-radius:var(--border-radius-circular); 18 | img { inline-size:var(--p-image-item-size) ; block-size:var(--p-image-item-size); } 19 | 20 | &.is-smaller { 21 | $size-item: pxToRem(32); 22 | --p-image-item-full-size: #{$size-item}; 23 | 24 | $size-item-image: pxToRem(15); 25 | --p-image-item-size: #{$size-item-image}; 26 | } 27 | #{$theme-dark} & { 28 | --p-image-item-bg-color: var(--color-neutral-85); 29 | --p-image-item-border-color: var(--color-neutral-80); 30 | } 31 | } -------------------------------------------------------------------------------- /src/sdk/proto/application.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package application; 3 | 4 | service Application { 5 | rpc Start (StartRequest) returns (StartResponse); 6 | rpc ListAll (ListRequest) returns (ListResponse); 7 | rpc CreateBot (CreateBotRequest) returns (CreateBotResponse); 8 | rpc UpdateStatus (UpdateStatusRequest) returns (UpdateStatusResponse); 9 | } 10 | 11 | message CreateBotRequest { 12 | string name = 1; 13 | int32 engine = 2; 14 | } 15 | 16 | message CreateBotResponse { 17 | bool success = 2; 18 | string id = 1; 19 | } 20 | 21 | message ListRequest {} 22 | 23 | message BotInfo { 24 | string id = 1; 25 | string name = 2; 26 | uint32 status = 4; 27 | string engine = 5; 28 | // optional string absolute_path = 3; 29 | } 30 | 31 | message ListResponse { 32 | repeated BotInfo data = 1; 33 | } 34 | 35 | message StartRequest { 36 | string bot_id = 1; 37 | } 38 | 39 | message StartResponse { 40 | bool success = 1; 41 | } 42 | 43 | enum UpdateStatusTypes { 44 | Start = 0; 45 | Stop = 1; 46 | Restart = 2; 47 | } 48 | 49 | message UpdateStatusRequest { 50 | string bot_id = 1; 51 | UpdateStatusTypes status = 2; 52 | } 53 | 54 | message UpdateStatusResponse { 55 | bool success = 1; 56 | } 57 | -------------------------------------------------------------------------------- /src/assets/background.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/sdk/core.ts: -------------------------------------------------------------------------------- 1 | import protoLoader from '@grpc/proto-loader'; 2 | import grpcjs from '@grpc/grpc-js'; 3 | 4 | // Load the .proto files and define package 5 | const packageDefinition = protoLoader.loadSync([ 6 | (`./src/sdk/proto/application.proto`), 7 | (`./src/sdk/proto/broadcast.proto`), 8 | (`./src/sdk/proto/system.proto`), 9 | ], { 10 | longs: String, 11 | enums: Number, // Maybe String? 12 | keepCase: true, 13 | defaults: true, 14 | oneofs: true 15 | }); 16 | 17 | // Load both bot and broadcast services 18 | const protoBot = grpcjs.loadPackageDefinition(packageDefinition).application; 19 | const protoBroadcast = grpcjs.loadPackageDefinition(packageDefinition).broadcast; 20 | 21 | export const clients = { 22 | bot: new protoBot.Application('localhost:50051', grpcjs.credentials.createInsecure()), 23 | broadcast: new protoBroadcast.BroadcastService('localhost:50051', grpcjs.credentials.createInsecure()) // Use broadcast service client 24 | } 25 | 26 | export default class CoreAbstraction { 27 | Clients = clients; 28 | constructor(address: string) { } 29 | 30 | async reconnect() { 31 | this.Clients = { 32 | bot: new protoBot.Application('localhost:50051', grpcjs.credentials.createInsecure()), 33 | broadcast: new protoBroadcast.BroadcastService('localhost:50051', grpcjs.credentials.createInsecure()) // Use broadcast service client 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/styles/7-components/_file-preview.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .file-preview { 3 | --p-file-preview-text-color: var(--color-neutral-20); 4 | --p-file-preview-bg-color: var(--color-neutral-0); 5 | --p-file-preview-border-color: var(--color-neutral-5); 6 | 7 | position: relative; 8 | display: grid; 9 | place-content: center; 10 | inline-size: pxToRem(205); 11 | aspect-ratio: 16 / 10; 12 | gap: pxToRem(8); 13 | color: hsl(var(--p-file-preview-text-color)); 14 | background-color: hsl(var(--p-file-preview-bg-color)); 15 | border: solid pxToRem(1) hsl(var(--p-file-preview-border-color)); 16 | border-radius: var(--border-radius-small); 17 | overflow: hidden; 18 | 19 | &:where(:focus, :hover) { 20 | .file-preview-image { opacity:1; } 21 | } 22 | 23 | &-image { 24 | position:absolute; inset:0; inline-size:100%; block-size:100%; opacity:0.65; transition:opacity var(--transition); 25 | img { display:block; inline-size:100%; block-size:100%; object-fit:cover; } 26 | } 27 | &-content { position:relative; display:grid; gap:pxToRem(8); justify-items:center; } 28 | .avatar {} 29 | &.is-with-image { border-width:0; } 30 | &.is-full-cover-image { place-content:revert; } 31 | 32 | #{$theme-dark} & { 33 | --p-file-preview-text-color: var(--color-neutral-20); 34 | --p-file-preview-bg-color: var(--color-neutral-90); 35 | --p-file-preview-border-color: var(--color-neutral-85); 36 | } 37 | } -------------------------------------------------------------------------------- /src/styles/8-grids/_grid-1-1.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .grid-1-1 { 4 | display: grid; 5 | &.is-full-page { 6 | --p-side-1-color: var(--color-neutral-5); 7 | --p-side-2-color: var(--color-neutral-0); 8 | 9 | #{$theme-dark} &{ 10 | --p-side-1-color: var(--color-neutral-90); 11 | --p-side-2-color: var(--color-neutral-105); 12 | } 13 | @media #{$break1} { 14 | grid-template-rows:auto 1fr; 15 | min-block-size:100vh; min-block-size:100dvh; 16 | background-color: hsl(var(--p-side-2-color)); 17 | .grid-1-1-col-2 { 18 | .container { 19 | $padding-block: pxToRem(0); 20 | --container-padding-block: #{$padding-block}; 21 | } 22 | } 23 | .grid-1-1-col-1 { 24 | .container { 25 | $padding-block: pxToRem(16); 26 | --container-padding-block: #{$padding-block}; 27 | } 28 | } 29 | } 30 | @media #{$break2open} { 31 | .grid-1-1-col { 32 | &-1 { 33 | background-color: hsl(var(--p-side-1-color)); 34 | } 35 | &-2 { 36 | background-color: hsl(var(--p-side-2-color)); 37 | > .container { 38 | block-size:100vh; block-size:100lvh; 39 | } 40 | } 41 | } 42 | } 43 | } 44 | 45 | @media #{$break2open} { 46 | grid-template-columns: repeat(2, 1fr); 47 | &-col { 48 | &-1 { 49 | 50 | } 51 | &-2 { 52 | 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/styles/7-components/_clickable-list.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .clickable-list { 3 | --p-clickable-button-bg-color-hover: var(--color-neutral-10); 4 | --p-clickable-title-text-color: var(--color-neutral-60); 5 | --p-clickable-desc-text-color: var(--color-neutral-50); 6 | --p-clickable-sep-color: var(--color-neutral-20); 7 | --color-border: var(--color-neutral-15); /* override global */ 8 | 9 | &-item { 10 | padding-block:pxToRem(4); -webkit-user-select:none; user-select:none; 11 | &:not(:last-child) { 12 | border-block-end:solid pxToRem(1) hsl(var(--color-border)); 13 | } 14 | } 15 | &-button { 16 | display:block; padding-block:pxToRem(8); padding-inline:pxToRem(16); border-radius:var(--border-radius-small); 17 | &:hover, &:focus { background-color:hsl(var(--p-clickable-button-bg-color-hover)); } 18 | } 19 | 20 | &-title { 21 | color:hsl(var(--p-clickable-title-text-color)); 22 | &-sep { color:hsl(var(--p-clickable-sep-color)); margin-inline:pxToRem(4); } 23 | } 24 | &-desc { color:hsl(var(--p-clickable-desc-text-color)); font-size:var(--font-size-00); } 25 | 26 | #{$theme-dark} & { 27 | --p-clickable-button-bg-color-hover: var(--color-neutral-85); 28 | --p-clickable-title-text-color: var(--color-neutral-10); 29 | --p-clickable-desc-text-color: var(--color-neutral-20); 30 | --p-clickable-sep-color: var(--color-neutral-80); 31 | 32 | --color-border: var(--color-neutral-80); /* override global */ 33 | } 34 | } -------------------------------------------------------------------------------- /src/styles/abstract/mixins/_scroll.scss: -------------------------------------------------------------------------------- 1 | @use '../../abstract/functions/pxToRem' as *; 2 | @use '../../abstract/variables/common' as *; 3 | @mixin scroll { 4 | &::-webkit-scrollbar { 5 | opacity: 0.7; 6 | width: pxToRem(8); 7 | height: pxToRem(8); 8 | } 9 | 10 | &::-webkit-scrollbar-track { 11 | border-radius: pxToRem(4); 12 | margin-right: pxToRem(8); 13 | } 14 | 15 | &::-webkit-scrollbar-thumb { 16 | border-radius: pxToRem(4); 17 | background: hsl(var(--scroll-color)); 18 | } 19 | 20 | &::-webkit-scrollbar-corner { 21 | background: hsl(var(--scroll-color)); 22 | border-radius: pxToRem(6); 23 | } 24 | } 25 | 26 | @mixin tableScroll { 27 | --p-track-bg-color: var(--track-bg-color, var(--color-neutral-5)); 28 | --p-track-border-color: var(--track-border-color, var(--color-neutral-10)); 29 | --p-scroll-bg-color: var(--scroll-bg-color, var(--color-neutral-15)); 30 | ::-webkit-scrollbar { 31 | width: 12px; 32 | } 33 | 34 | ::-webkit-scrollbar-track { 35 | border-block:solid pxToRem(1) hsl(var(--p-track-border-color)); 36 | background-color: hsl(var(--p-track-bg-color)); 37 | border-radius: 0; 38 | } 39 | 40 | ::-webkit-scrollbar-thumb { 41 | border-radius: 100px; 42 | border: pxToRem(3) solid transparent; 43 | background-clip: content-box; 44 | background-color: hsl(var(--p-scroll-bg-color)); 45 | } 46 | 47 | #{$theme-dark} & { 48 | --track-bg-color: var(--color-neutral-105); 49 | --track-border-color: var(--color-neutral-85); 50 | --scroll-bg-color: var(--color-neutral-80); 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/styles/7-components/_top-banner.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .top-banner { 3 | position:relative; overflow:hidden; display:flex; justify-content:center; 4 | padding-block:pxToRem(5); padding-inline:pxToRem(12); 5 | 6 | &-bg { 7 | position:absolute; inset:0; 8 | block-size:60px; inline-size:100%; 9 | svg, img { 10 | animation:rotate 7s infinite linear; 11 | inline-size:100vw; 12 | filter:blur(8px); 13 | max-inline-size:none; max-block-size:none; 14 | @media (prefers-reduced-motion) { animation:none; } 15 | } 16 | } 17 | &-bg-1 { 18 | position:absolute; inset-inline-start:0; inset-block-start:0; 19 | transform:translateX(-60%) translateY(-35%); /* for inline svg */ 20 | 21 | inline-size:100vw; 22 | } 23 | &-bg-2 { 24 | position:absolute; inset-inline-end:0; inset-block-start:0; 25 | transform:translateX(55%) translateY(-50%); /* for inline svg */ 26 | inline-size:100vw; 27 | } 28 | &-content { position:relative; z-index:1; line-height:pxToRem(50); transition:var(--transition); } 29 | &-button { position:absolute; inset-block:0; inset-inline-end:pxToRem(12); } 30 | 31 | [data-banner-hidden] & { 32 | display: none; 33 | } 34 | @media #{$break1} { 35 | inline-size:100%; padding:pxToRem(16); 36 | &-content { display:flex; flex-direction:column; inline-size:100%; line-height:1.5; transition:var(--transition); } 37 | &-button { 38 | position:static; line-height:1; align-self:end; order:-1; 39 | margin-block-start:-4px; margin-inline-end:-5px; margin-block-end:pxToRem(8); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/styles/7-components/_secondary-tabs.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .secondary-tabs { 3 | --p-drop-tab-text-color: var(--color-neutral-60); 4 | --p-drop-tab-bg-color: var(--transparent); 5 | 6 | $drop-tab-height: pxToRem(32); 7 | --p-drop-tab-height: #{$drop-tab-height}; 8 | 9 | $drop-tab-padding-horizontal: pxToRem(12); 10 | --p-drop-tab-padding-horizontal: #{$drop-tab-padding-horizontal}; 11 | 12 | display:flex; gap:pxToRem(16); 13 | 14 | &-item {} 15 | &-button { 16 | display:block; padding-inline:var(--p-drop-tab-padding-horizontal); user-select:none; 17 | line-height:var(--p-drop-tab-height); border-radius:var(--border-radius-small); 18 | color:hsl(var(--p-drop-tab-text-color)); background-color:hsl(var(--p-drop-tab-bg-color)); 19 | &:where(#{$disabled}) { --p-drop-tab-bg-color:var(--color-neutral-10); cursor:default; } 20 | &:where(:not(#{$disabled})) { cursor:pointer; } 21 | } 22 | 23 | &:where(.is-large) { 24 | $drop-tab-height: pxToRem(38); 25 | --p-drop-tab-height: #{$drop-tab-height}; 26 | 27 | $drop-tab-padding-horizontal: pxToRem(20); 28 | --p-drop-tab-padding-horizontal: #{$drop-tab-padding-horizontal}; 29 | } 30 | &:where(.is-stretch) { 31 | inline-size:100%; 32 | .secondary-tabs { 33 | &-item { flex:1; } 34 | &-button { inline-size:100%; text-align:center; } 35 | } 36 | } 37 | #{$theme-dark} & { 38 | --p-drop-tab-text-color: var(--color-neutral-20); 39 | &-button { 40 | &:where(#{$disabled}) { 41 | --p-drop-tab-bg-color: var(--color-neutral-85); 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/styles/6-elements/_tooltip.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .tooltip { 3 | /* Light Theme */ 4 | --p-tooltip-text-color: var(--color-neutral-10); 5 | --p-tooltip--bg-color: var(--color-neutral-60); 6 | /* End Light theme variables */ 7 | 8 | position:relative; line-height:1; 9 | [class*="icon"]::before { vertical-align:middle; } 10 | &-popup { 11 | display: none; 12 | position:absolute; inset-inline-start:0; inset-block-end:calc(100% + 6px); 13 | padding-block:pxToRem(4); padding-inline:pxToRem(8); max-inline-size:pxToRem(180); inline-size:max-content; 14 | background-color: hsl(var(--p-tooltip--bg-color)); 15 | font-size:var(--font-size-0); line-height:1.5; 16 | color: hsl(var(--p-tooltip-text-color)); 17 | border-radius: var(--border-radius-small); 18 | 19 | &.is-bottom { inset-block-start:calc(100% + 10px); inset-block-end:auto; } 20 | &.is-center { inset-inline-start:50%; transform:translateX(-50%); } 21 | &.is-end { inset-inline-start:auto; inset-inline-end:0; } 22 | 23 | //&::before { 24 | // position:absolute; inset-block-start:100%; inset-inline-start:pxToRem(25); 25 | // content: ""; display:block; inline-size:pxToRem(12); block-size:pxToRem(6); 26 | // clip-path: polygon(0% 0%, 100% 0%, 50% 100%); 27 | // background-color: hsl(var(--p-bg-color)); 28 | //} 29 | } 30 | &:hover, &:focus-visible { 31 | .tooltip-popup { display:block; white-space: initial; } 32 | } 33 | 34 | /* Theme Dark */ 35 | #{$theme-dark} & { 36 | //--p-bg-color-default: var(--color-neutral-10); 37 | //--p-pill-text-color-default: var(--color-neutral-200); 38 | } 39 | } -------------------------------------------------------------------------------- /src/styles/7-components/_toggle-button.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .toggle-button { 3 | --p-icon-toggle-bg-color: var(--color-neutral-0); 4 | --p-icon-toggle-border-color: var(--color-neutral-15); 5 | 6 | --p-icon-text-color: var(--p-icon-text-color-default); 7 | --p-icon-text-color-default: var(--color-neutral-60); 8 | --p-icon-text-color-didabled: var(--color-neutral-20); 9 | 10 | --p-button-color: var(--p-button-color-default); 11 | --p-button-color-default: var(--transparent); 12 | --p-button-color-selected: var(--color-neutral-10); 13 | 14 | background-color: hsl(var(--p-icon-toggle-bg-color)); 15 | &-list { 16 | display:flex; gap:pxToRem(8); padding:pxToRem(2); 17 | border:solid pxToRem(1) hsl(var(--p-icon-toggle-border-color)); border-radius:var(--border-radius-xsmall); 18 | } 19 | &-item {} 20 | &-element { 21 | display:grid; place-content:center; 22 | inline-size:pxToRem(36); block-size:pxToRem(36); 23 | background-color:hsl(var(--p-button-color)); color:hsl(var(--p-icon-text-color)); border-radius:var(--border-radius-xsmall); 24 | &.is-selected { --p-button-color: var(--p-button-color-selected); } 25 | &#{$disabled} { 26 | --p-icon-text-color: var(--p-icon-text-color-didabled); 27 | cursor: initial; 28 | } 29 | } 30 | 31 | #{$theme-dark} & { 32 | --p-icon-toggle-bg-color: var(--color-neutral-90); 33 | --p-icon-toggle-border-color: var(--color-neutral-80); 34 | 35 | --p-icon-text-color-default: var(--color-neutral-20); 36 | --p-icon-text-color-didabled: var(--color-neutral-70); 37 | 38 | --p-button-color-selected: var(--color-neutral-80); 39 | } 40 | } -------------------------------------------------------------------------------- /src/styles/6-elements/form/_interactive-text-output.scss: -------------------------------------------------------------------------------- 1 | @use '../../abstract' as *; 2 | .interactive-text-output { 3 | 4 | --p-text-color: var(--color-neutral-60); 5 | --p-background-color: var(--color-neutral-10); 6 | 7 | position:relative; 8 | display:flex; gap:pxToRem(12); max-inline-size:100%; min-block-size:pxToRem(28); 9 | padding-inline:pxToRem(8); padding-block:pxToRem(4); 10 | inline-size: fit-content; min-inline-size:pxToRem(146); 11 | border-radius: var(--border-radius-xsmall); 12 | color:hsl(var(--p-text-color)); line-height:1; 13 | 14 | .text { @include break-word(); flex:1; align-self:center; font-family:var(--code-font); } 15 | 16 | &:is(:hover, :has(:focus) ) { 17 | background-color: hsl(var(--p-background-color)); 18 | .interactive-text-output-button { opacity:1; } 19 | } 20 | /* wrapper for button/s */ 21 | &-buttons { display:flex; gap:pxToRem(8); align-self:start; } 22 | 23 | &-button { 24 | border-radius: var(--border-radius-circular); 25 | &.is-hidden { opacity:0; } 26 | } 27 | 28 | &.is-buttons-on-top { 29 | background-color:hsl(var(--p-background-color)); 30 | .interactive-text-output-buttons { 31 | position:absolute; inset-inline-end:pxToRem(8); inset-block-start:pxToRem(4); 32 | filter: drop-shadow(0px 0px pxToRem(4) hsl(var(--p-background-color))) 33 | drop-shadow(0px 0px pxToRem(6) hsl(var(--p-background-color))) 34 | drop-shadow(0px 0px pxToRem(8) hsl(var(--p-background-color))); 35 | } 36 | } 37 | 38 | #{$theme-dark} & { 39 | --p-text-color: var(--color-neutral-20); 40 | --p-background-color: var(--color-neutral-80); 41 | } 42 | } -------------------------------------------------------------------------------- /src/styles/7-components/_user-profile.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .user-profile { 4 | display: grid; 5 | grid-template-columns: auto 1fr; 6 | column-gap: pxToRem(16); 7 | row-gap: pxToRem(12); 8 | 9 | &-sep { grid-column:span 2; border-block-start:solid pxToRem(1) hsl(var(--color-border)); } 10 | &-button { 11 | /* variables */ 12 | --p-name-color-text: var(--color-neutral-60); 13 | --p-title-color-text: var(--color-neutral-50); 14 | --p-icon-color: var(--color-neutral-20); 15 | 16 | position:relative; z-index:2; 17 | display:flex; block-size:100%; align-items:center; padding-inline:pxToRem(24); gap:pxToRem(12); 18 | background-color:hsl(var(--p-main-header-bg-color)); /* get from parent partial */ 19 | > * { flex-shrink:0; } 20 | [class*="icon"] { font-size:var(--icon-size-medium); color:hsl(var(--p-icon-color)); transition:var(--transition); } 21 | &.is-open { 22 | [class*="icon"] { transform:rotateZ(180deg); } 23 | } 24 | #{$theme-dark} & { 25 | --p-name-color-text: var(--color-neutral-5); 26 | --p-title-color-text: var(--color-neutral-20); 27 | --p-icon-color: var(--color-neutral-20); 28 | } 29 | } 30 | &-info { 31 | flex:1; font-size:var(--font-size-0); line-height:1.35; 32 | > { 33 | .text, 34 | .name, 35 | .title { display:block ;} 36 | } 37 | .name { @include trim(); color:hsl(var(--p-name-color-text)); } 38 | .title { @include trim(); color:hsl(var(--p-title-color-text));} 39 | } 40 | 41 | @media #{$break3open} { 42 | border-inline-start:solid pxToRem(1) hsl(var(--p-main-header-border-color)); 43 | &-button { min-inline-size:pxToRem(240); } 44 | } 45 | } -------------------------------------------------------------------------------- /src/styles/6-elements/_inline-tag.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .inline-tag { 3 | $tag-height: pxToRem(22); 4 | --p-inline-tag-height: #{$tag-height}; 5 | 6 | $padding-inline: pxToRem(6); 7 | --p-inline-tag-padding-inline: #{$padding-inline}; 8 | 9 | --p-inline-tag-text-color: var(--inline-tag-text-color, var(--p-inline-tag-text-color-default)); 10 | --p-inline-tag-bg-color: var(--inline-tag-bg-color, var(--p-inline-tag-bg-color-default)); 11 | 12 | --p-inline-tag-text-color-default: var(--p-text-color, var(--color-neutral-60)); 13 | --p-inline-tag-bg-color-default: var(--color-neutral-10); 14 | 15 | --p-inline-tag-text-color-disabled: var(--color-neutral-15); 16 | 17 | 18 | --p-inline-tag-text-color-info: var(--color-neutral-0); 19 | --p-inline-tag-bg-color-info: var(--color-information-100); 20 | 21 | display:inline-grid; place-content:center; padding-inline:var(--p-inline-tag-padding-inline); 22 | 23 | background-color: hsl(var(--p-inline-tag-bg-color)); 24 | color: hsl(var(--p-inline-tag-text-color)); 25 | border-radius: var(--border-radius-xsmall); 26 | 27 | flex-shrink:0; font-weight:600; 28 | 29 | &.is-info { 30 | --p-inline-tag-text-color: var(--p-inline-tag-text-color-info); 31 | --p-inline-tag-bg-color: var(--p-inline-tag-bg-color-info); 32 | } 33 | 34 | &:where(#{$disabled}) { 35 | --p-inline-tag-text-color: var(--p-inline-tag-text-color-disabled); 36 | } 37 | 38 | /* Theme Dark */ 39 | #{$theme-dark} & { 40 | --p-inline-tag-text-color-default: var(--p-text-color, var(--color-neutral-20)); 41 | --p-inline-tag-bg-color-default: var(--color-neutral-80); 42 | 43 | --p-inline-tag-text-color-disabled: var(--color-neutral-60); 44 | } 45 | } -------------------------------------------------------------------------------- /src/styles/7-components/_progress-bar.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .progress-bar { 3 | --p-graph-bg-color: var(--color-neutral-15); 4 | --p-graph-color-fill: var(--color-information-100); 5 | --p-graph-color-warning: var(--color-warning-100); 6 | --p-graph-color-danger: var(--color-danger-100); 7 | 8 | --p-graph-icon-color: var(--color-neutral-50); 9 | --p-graph-text-color: var(--color-neutral-60); 10 | --p-graph-used-text-color: var(--color-neutral-70); 11 | --p-graph-max-text-color: var(--color-neutral-50); 12 | 13 | display:flex; flex-direction:column; gap:pxToRem(8); 14 | -webkit-user-select:none; user-select:none; 15 | 16 | &-container { 17 | display:flex; block-size:pxToRem(8); border-radius:var(--border-radius-xsmall); 18 | background-color:hsl(var(--p-graph-bg-color)); 19 | /* fill graph */ 20 | &::before { 21 | content:""; display:block; block-size:100%; flex-basis:var(--graph-size, 0); 22 | border-radius:inherit; inline-size:var(--graph-size); 23 | background-color:hsl(var(--p-graph-color-fill)); 24 | } 25 | /* states */ 26 | &.is-warning { --p-graph-color-fill:var(--p-graph-color-warning); } 27 | &.is-danger { --p-graph-color-fill:var(--p-graph-color-danger); } 28 | } 29 | &-top-line { 30 | color:hsl(var(--p-graph-text-color)); 31 | [class*="icon"] { color:hsl(var(--p-graph-icon-color)); } 32 | } 33 | &-text-used { color:hsl(var(--p-graph-used-text-color)); } 34 | &-text-max { color:hsl(var(--p-graph-max-text-color)); } 35 | 36 | 37 | #{$theme-dark} & { 38 | --p-graph-bg-color: var(--color-neutral-85); 39 | --p-graph-icon-color: var(--color-neutral-20); 40 | --p-graph-text-color: var(--color-neutral-20); 41 | --p-graph-used-text-color: var(--color-neutral-20); 42 | } 43 | } -------------------------------------------------------------------------------- /src/styles/8-grids/_wizard-secondary.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract/index' as *; 2 | 3 | .wizard-secondary { 4 | --wizard-aecondary-bg-color: var(--color-neutral-0); 5 | display:block; min-block-size:100dvh; padding-inline:pxToRem(32); 6 | background-color:hsl(var(--wizard-aecondary-bg-color)); 7 | &-container { max-inline-size:pxToRem(1200); margin-inline:auto; } 8 | &-header { 9 | position:sticky; z-index:1; inset-block-start:0; 10 | display:flex; flex-direction:column; gap:pxToRem(16); 11 | padding-block-start:pxToRem(32); padding-block-end:pxToRem(16); 12 | background-color:hsl(var(--wizard-aecondary-bg-color)); 13 | } 14 | &-content { 15 | display:flex; gap:pxToRem(32); padding-block-start:pxToRem(16); 16 | &-sep { flex-basis:pxToRem(1); flex-shrink:0; background-color:hsl(var(--color-border)); } 17 | } 18 | &-options { 19 | position:sticky; inset-block-end:0; display:flex; gap:pxToRem(16); justify-content:space-between; 20 | padding-block:pxToRem(32); border-block-start:solid pxToRem(1) hsl(var(--color-border)); margin-block-start:pxToRem(32); 21 | background-color:hsl(var(--wizard-aecondary-bg-color)); 22 | &-start { display:flex; gap:pxToRem(16); } 23 | &-end { display:flex; gap:pxToRem(16); } 24 | } 25 | 26 | #{$theme-dark} & { 27 | --wizard-aecondary-bg-color: var(--color-neutral-90); 28 | } 29 | 30 | @media #{$break1} { 31 | &-options { 32 | flex-direction:column-reverse; 33 | &-start, 34 | &-end { flex-direction:column-reverse; } 35 | } 36 | } 37 | @media (max-width:1127.99px) { 38 | &-content { flex-direction:column; } 39 | } 40 | 41 | @media (min-width: 1128px) { 42 | &-content { 43 | &-1 { flex:2.25; } 44 | &-2 { flex:1; } 45 | &-sticky { position:sticky; inset-block-start:pxToRem(155); } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/sdk/test.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from './enums'; 2 | import Crabshell from './index'; 3 | import express from 'express'; 4 | const app = express(); 5 | 6 | const can = new Crabshell(`127.0.0.1:50051`) 7 | const call = can.core.Clients.broadcast.Subscribe({}); 8 | 9 | call.on('data', (response: { message: string }) => { 10 | console.log('Received:', response.message); 11 | }); 12 | 13 | call.on('end', () => { 14 | console.log('Stream ended'); 15 | can.core.reconnect(); 16 | }); 17 | 18 | call.on('error', (e) => { 19 | console.error('Error:', e); 20 | // Connection broke from the server, reconnect? 21 | if (e.code == 14) { 22 | // Reconnect logic 23 | } 24 | }); 25 | 26 | app.get("/create-dummy", async (req, res) => { 27 | const start = new Date(); 28 | 29 | const bot = await can.create({ 30 | name: "Master Machine", 31 | engine: Engine.Node, 32 | }) 33 | 34 | console.log(bot) 35 | 36 | if (bot != null) { 37 | console.log(bot) 38 | res.json({ 39 | success: true, 40 | time: new Date().getTime() - start.getTime(), 41 | data: bot.data 42 | }) 43 | } else { 44 | res.status(500).json({ success: false }); 45 | } 46 | }) 47 | 48 | app.get("/fake-io", (req, res) => { 49 | const text = req.query.text; 50 | console.log(text) 51 | }) 52 | 53 | 54 | app.get("/start/:id/:status", async (req, res) => { 55 | const { id, status } = req.params 56 | 57 | const results = await can.update_status_by_id(id, parseInt(status)) 58 | res.json(results) 59 | }) 60 | 61 | // HTTP Route for Start Request (bot service) 62 | app.get('/', async (req, res) => { 63 | const bots = await can.fetch_all_raw() 64 | res.json({ 65 | success: true, 66 | data: bots?.data // Response from gRPC server 67 | }); 68 | }); 69 | 70 | const random_port = 7200; 71 | app.listen(random_port, function () { 72 | console.log(`Live at http://127.0.0.1:${random_port}`); 73 | }); 74 | -------------------------------------------------------------------------------- /src/styles/7-components/_main-header.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | :root { 3 | $main-header-height: pxToRem(64); 4 | --main-header-height: #{$main-header-height}; 5 | } 6 | .main-header { 7 | --p-main-header-bg-color: var(--color-neutral-0); 8 | --p-main-header-border-color: var(--color-border); 9 | 10 | display:flex; align-items:center; gap:pxToRem(24); block-size:var(--main-header-height); padding-inline:pxToRem(24); 11 | background-color:hsl(var(--p-main-header-bg-color)); 12 | border-block-end:solid pxToRem(1) hsl(var(--p-main-header-border-color)); 13 | -webkit-user-select:none; user-select:none; 14 | 15 | > * { min-inline-size:0; } 16 | &-end { flex-shrink:0; display:flex; align-items:center; block-size:100%; gap:pxToRem(24); } 17 | 18 | /* override */ 19 | .drop { 20 | @media #{$break1}, #{$break2} { 21 | position:fixed; z-index:5; inset-block-start:var(--main-header-height); inset-inline:0; 22 | inline-size:100%; max-inline-size:none; 23 | } 24 | } 25 | 26 | 27 | #{$theme-dark} & { 28 | --p-main-header-bg-color: var(--color-neutral-105); 29 | } 30 | 31 | @media #{$break1}, #{$break2} { 32 | gap:pxToRem(8); padding-inline-start:pxToRem(8); 33 | .logo { margin-inline-end:auto; } 34 | .user-profile { 35 | .drop { max-inline-size:initial; } 36 | .drop-wrapper { position:static; } 37 | } 38 | #Support { inset-block-end:0; overflow:auto; border-start-start-radius:0; border-start-end-radius:0; } 39 | } 40 | @media #{$break3open} { 41 | &-end { margin-inline-start:auto; } 42 | 43 | .user-profile-button + .drop { 44 | border-start-start-radius:0; border-start-end-radius:0; 45 | inset-inline:pxToRem(-1) 0; inset-block-start:100%; 46 | } 47 | #Support { 48 | margin-block-start:pxToRem(2); 49 | &.drop { 50 | &::before, &::after { inset-block-start:pxToRem(-7); } 51 | &::before { inline-size:pxToRem(16); } 52 | &::after { inline-size:pxToRem(17); } 53 | } 54 | } 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/styles/7-components/_upload-image.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .upload-image { 3 | $upload-image-size-default: #{pxToRem(40)}; 4 | 5 | --p-upload-image-size: var(--upload-image-size, #{$upload-image-size-default}); 6 | --p-upload-bg-color: var(--color-neutral-10); 7 | --p-upload-border-color: var(--color-neutral-10); 8 | --p-upload-icon-color: var(--color-neutral-20); 9 | --p-upload-text-color: var(--color-neutral-50); 10 | 11 | position:relative; display:grid; place-content:center; 12 | inline-size: var(--p-upload-image-size); 13 | block-size: var(--p-upload-image-size); 14 | background-color: hsl(var(--p-upload-bg-color)); 15 | border:solid pxToRem(1) hsl(var(--p-upload-border-color)); 16 | border-radius:50%; flex-shrink:0; 17 | 18 | [class*="icon"] { position:relative; z-index:2; color:hsl(var(--p-upload-icon-color)); } 19 | .text { position:relative; z-index:2; color:hsl(var(--p-upload-text-color)); } 20 | .progress { 21 | --progress:var(--progress-value, 0); 22 | position:absolute; z-index:1; inset:0; border-radius:var(--border-radius-circular); 23 | background: 24 | radial-gradient( 25 | hsl(var(--p-upload-bg-color)) 0%, 26 | hsl(var(--p-upload-bg-color)) 64%, 27 | transparent 64.01%, 28 | transparent 100%), 29 | 30 | conic-gradient( 31 | hsl(194 66% 50%) 0%, 32 | hsl(97 66% 50%) calc(var(--progress) * 1%), 33 | hsl(0 0% 0% / 0%) calc(var(--progress) * 1%), 34 | hsl(0 0% 0% / 0%) 100%); 35 | } 36 | &.is-finished { 37 | --p-upload-border-color: var(--p-upload-border-color); 38 | .progress{ display:none; } 39 | #{$theme-dark} & { --p-upload-border-color: var(--color-neutral-80); } 40 | } 41 | /* dark theme */ 42 | #{$theme-dark} & { 43 | --p-upload-bg-color: var(--color-neutral-85); 44 | --p-upload-border-color: var(--color-neutral-85); 45 | --p-upload-icon-color: var(--color-neutral-20); 46 | --p-upload-text-color: var(--color-neutral-20); 47 | } 48 | } -------------------------------------------------------------------------------- /src/styles/6-elements/_box.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .box { 4 | --p-box-text-color: var(--color-neutral-60); 5 | 6 | --p-box-background-color: var(--p-box-background-color-default); 7 | --p-box-background-color-default: var(--color-neutral-5); 8 | --p-box-background-color-hover: var(--color-neutral-10); 9 | 10 | --p-box-border-color: var(--color-neutral-15); 11 | 12 | --p-box-padding: var(--box-padding, #{pxToRem(24)} ); 13 | --p-box-border-radius: var(--box-border-radius, var(--border-radius-xsmall)); 14 | 15 | position: relative; 16 | background-color: hsl(var(--p-box-background-color)); 17 | border: solid pxToRem(1) hsl(var(--p-box-border-color)); 18 | 19 | border-radius: var(--p-box-border-radius); 20 | padding: var(--p-box-padding); 21 | color: hsl(var(--p-box-text-color)); 22 | 23 | max-inline-size:100%; 24 | 25 | &-footer-button { 26 | position:absolute; inset-inline:0; inset-block-end:0; text-align:center; 27 | inline-size:100%; padding-block-start:pxToRem(60); padding-block-end:pxToRem(8); 28 | background: linear-gradient( 29 | to bottom, 30 | hsl(var(--p-box-background-color) / 0), hsl(var(--p-box-background-color) / 1) 31 | ); 32 | } 33 | 34 | &.is-border-dashed { border-style:dashed; } 35 | &.is-hover-with-file { --p-box-background-color: var(--p-box-background-color-hover); } 36 | 37 | #{$theme-dark} & { 38 | --p-box-text-color: var(--color-neutral-5); 39 | --p-box-background-color-default: var(--color-neutral-85); 40 | --p-box-background-color-hover: var(--color-neutral-80); 41 | --p-box-border-color: var(--color-neutral-80); 42 | } 43 | } 44 | 45 | .boxes-wrapper { 46 | display:grid; 47 | .box { 48 | border-radius: 0; 49 | &:first-child { 50 | border-start-start-radius: var(--border-radius-xsmall); 51 | border-start-end-radius: var(--border-radius-xsmall); 52 | } 53 | &:last-child { 54 | border-top: 0; 55 | border-end-start-radius: var(--border-radius-xsmall); 56 | border-end-end-radius: var(--border-radius-xsmall); 57 | } 58 | &:not(:first-child):not(:last-child) { 59 | border-block-start: 0; 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /src/styles/8-grids/_grid-with-side.scss: -------------------------------------------------------------------------------- 1 | @use "../abstract" as *; 2 | .grid-with-side { 3 | position: relative; 4 | --p-side-size: #{pxToRem(200)}; 5 | > { 6 | :where(.alert) { grid-area:alert; } 7 | :where(.top-banner) { grid-area:alert; } 8 | :where(.main-header) { grid-area:header; } 9 | :where(.main-side) { grid-area:side; } 10 | :where(.main-content) { grid-area:main; } 11 | } 12 | 13 | @media #{$break1}, #{$break2} { 14 | .main-side { display:none; max-block-size:none; } 15 | 16 | &:where(.is-open) { 17 | .main-side { display:block; position:static; } 18 | .main-content { display:none; } 19 | } 20 | } 21 | @media #{$break3open} { 22 | display: grid; 23 | grid-template-columns: minmax(var(--p-side-size), auto) 1fr; 24 | grid-template-rows: auto auto 1fr; 25 | grid-template-areas: "alert alert" 26 | "header header" 27 | "side main"; 28 | > .main-content { max-inline-size:calc(100vw - var(--p-side-size)); } 29 | 30 | &.is-fixed-layout { 31 | block-size:100vh; block-size:100lvh; 32 | max-block-size:100vh; max-block-size:100lvh; 33 | .main-side { block-size:auto; } 34 | .main-content { overflow:auto; } 35 | } 36 | 37 | &.is-empty-side { 38 | grid-template-areas: "header header" 39 | "main main"; 40 | .main-side { block-size:unset; } 41 | .main-content > * { padding-inline-start:var(--p-side-size); } 42 | } 43 | .main-side { block-size:calc(100vh - var(--main-header-height)); } 44 | } 45 | } 46 | /* no side */ 47 | .is-fixed-alert-layout { 48 | @media #{$break3open} { 49 | display: flex; flex-direction:column; 50 | block-size:100vh; block-size:100lvh; 51 | max-block-size:100vh; max-block-size:100lvh; 52 | .main-content { overflow:auto; flex:1; } 53 | } 54 | } 55 | 56 | .main-content { 57 | position:relative; display:flex; flex-direction:column; flex:1; /* z-index:1; */ 58 | > * { flex-shrink:0; } 59 | } /* remove z-index, mage nug in modals */ 60 | .main-header { position:sticky; z-index:5; inset-block-start:0; } 61 | .main-side { position:sticky; z-index:5; inset-block-start:var(--main-header-height); max-block-size:100vh; overflow:hidden;} -------------------------------------------------------------------------------- /src/styles/7-components/_upload-file-box.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .upload-file-box { 3 | //--color-border: var(--color-neutral-50); 4 | --p-icon-file: var(--color-neutral-20); 5 | --p-title-color: var(--color-neutral-70); 6 | --p-info-text: var(--color-neutral-60); 7 | --p-file-size: var(--color-neutral-50); 8 | 9 | display: flex; 10 | flex-direction: column; 11 | justify-content: center; 12 | gap: pxToRem(16); 13 | 14 | 15 | &-list { 16 | @media #{$break2open} { 17 | border-block-start:solid pxToRem(1) hsl(var(--color-border)); padding-block-start:pxToRem(16); margin-block-start:pxToRem(8); 18 | } 19 | } 20 | &-title { 21 | color:hsl(var(--p-title-color)); vertical-align:baseline; 22 | + *,+ * *, + * [class*="icon"]::before { vertical-align:baseline; } 23 | } 24 | &-info, 25 | &-name { color:hsl(var(--p-info-text)); } 26 | &-size { 27 | color: hsl(var(--p-file-size)); 28 | &::before { content: "("; } 29 | &::after { content: ")"; } 30 | } 31 | &-image { 32 | $size: pxToRem(48); 33 | --p-size: #{$size}; 34 | 35 | --p-image-color: var(--color-neutral-60); 36 | --p-bg-color: var(--color-neutral-5); 37 | --p-border-color: var(--color-neutral-15); 38 | 39 | color: hsl(var(--p-image-color)); 40 | background-color: hsl(var(--p-bg-color)); 41 | border: solid pxToRem(1) hsl(var(--p-border-color)); 42 | 43 | display:grid; place-content:center; align-self:center; flex-shrink:0; 44 | inline-size:var(--p-size); block-size:var(--p-size); min-inline-size:0; 45 | border-radius:var(--border-radius-circular); 46 | 47 | @media #{$break1} { 48 | $size: pxToRem(40); 49 | --p-size: #{$size}; 50 | } 51 | 52 | #{$theme-dark} & { 53 | --p-image-color: var(--color-neutral-60); 54 | --p-bg-color: var(--color-neutral-90); 55 | --p-border-color: var(--color-neutral-80); 56 | } 57 | 58 | } 59 | .icon-document { color:hsl(var(--p-icon-file)); margin-inline-end:pxToRem(8); } 60 | 61 | @media #{$break1} { 62 | gap: pxToRem(8); 63 | &-list { grid-column:span 2; } 64 | } 65 | @media #{$break2open} { 66 | 67 | &-list { grid-column:2; } 68 | } 69 | /* Theme Dark */ 70 | #{$theme-dark} & { 71 | --p-title-color: var(--color-neutral-5); 72 | --p-info-text: var(--color-neutral-20); 73 | } 74 | } -------------------------------------------------------------------------------- /src/styles/7-components/_list.scss: -------------------------------------------------------------------------------- 1 | @use "../abstract" as *; 2 | .list { 3 | --p-list-text-color: var(--color-neutral-60); 4 | color: hsl(var(--p-list-text-color)); 5 | 6 | display:flex; flex-direction:column; gap:pxToRem(24); font-size:pxToRem(16); 7 | 8 | &-item { 9 | display:flex; align-items:baseline; gap:pxToRem(20); 10 | > * { vertical-align:middle; } 11 | [class*="icon"] { line-height:1; } 12 | .text { align-self:center; line-height:1.5; } 13 | } 14 | 15 | .icon-check { 16 | flex-shrink:0; display:inline-grid; place-content:center; 17 | inline-size:pxToRem(24); block-size:pxToRem(24); 18 | color:hsl(var(--color-neutral-0)); font-size:pxToRem(14); 19 | background-color:hsl(var(--color-primary-100)); border-radius:50%; 20 | } 21 | 22 | #{$theme-dark} & { 23 | --p-list-text-color: var(--color-neutral-20); 24 | } 25 | } 26 | 27 | .un-order-list { 28 | display:flex; flex-direction:column; 29 | list-style-type:disc; line-height:1.8; 30 | padding-inline-start:pxToRem(16); 31 | > *::marker { all:revert; } 32 | } 33 | 34 | .numeric-list { 35 | --p-numeric-border-color: var(--color-neutral-10); 36 | --p-numeric-bg-color: var(--color-neutral-5); 37 | --p-numeric-text-color: var(--color-neutral-60); 38 | counter-reset: number; 39 | display:grid; row-gap:pxToRem(24); 40 | &-item { 41 | counter-increment: number; 42 | display:flex; align-items:baseline; column-gap:pxToRem(24); 43 | &::before { 44 | content: counter(number); flex-shrink:0; 45 | display:grid; place-content:center; inline-size:pxToRem(32); block-size:pxToRem(32); 46 | background-color:hsl(var(--p-numeric-bg-color)); color:hsl(var(--p-numeric-text-color)); 47 | border:solid pxToRem(1) hsl(var(--p-numeric-border-color)); 48 | border-radius:var(--border-radius-circular); 49 | } 50 | } 51 | #{$theme-dark} & { 52 | --p-numeric-border-color: var(--color-neutral-80); 53 | --p-numeric-bg-color: var(--color-neutral-85); 54 | --p-numeric-text-color: var(--color-neutral-20); 55 | } 56 | } 57 | 58 | .order-list { 59 | counter-reset: number; 60 | display:flex; flex-direction:column; gap:pxToRem(32); 61 | 62 | &-item { 63 | counter-increment: number; 64 | display:flex; flex-direction:column; flex-wrap:wrap; gap:pxToRem(16); 65 | } 66 | &-content { 67 | display:flex; gap:pxToRem(16); 68 | &::before { content:counter(number); } 69 | &.is-hide-number::before { opacity:0; } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/pages/users/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Users

9 |
10 | 11 |
12 |
15 | 16 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | { 30 | [].map((bot) => { 31 | return ( 32 | 33 | 36 | 39 | 42 | 47 | 48 | ); 49 | }) 50 | } 51 | 52 |
IDUsernamePassword 24 | 25 |
34 | {bot.id} 35 | 37 | {bot.username} 38 | 40 | {bot.password} 41 | 43 | 46 |
53 |
54 |
55 |
56 |
57 | -------------------------------------------------------------------------------- /src/pages/applications/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | import can from "../../sdk/abstract"; 4 | 5 | const bots = await can.getApplicationList(); 6 | --- 7 | 8 | 9 |
10 |
11 |

Applications

12 |
13 | 14 |
15 |
18 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 33 | { 34 | bots.data.map((bot) => { 35 | return ( 36 | 37 | 40 | 41 | 42 | 43 | 48 | 49 | ); 50 | }) 51 | } 52 | 53 |
IDNameStatusEngine 28 | 29 |
38 | {bot.id} 39 | {bot.name}{bot.status}{bot.engine} 44 | 47 |
54 |
55 |
56 |
57 |
58 | -------------------------------------------------------------------------------- /src/styles/6-elements/_loader.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .loader { 3 | --loading: 0%; 4 | 5 | --p-loader-border-base-color: var(--color-neutral-10); 6 | --p-loader-base-full-color: var(--color-neutral-20); 7 | 8 | --p-loader-size: var(--loader-size, #{pxToRem(24)}); 9 | --p-loader-border-size: var(--loader-border-size, #{pxToRem(2.5)}); 10 | 11 | /* loading inner bg color */ 12 | --p-loader-bg-color: var(--loader-bg-color-default, var(--p-loader-bg-color-default)); 13 | --p-loader-bg-color-default: var(--loader-bg-color-light, var(--p-loader-bg-color-light)); 14 | --p-loader-bg-color-light: var(--color-neutral-5); 15 | --p-loader-bg-color-dark: var(--color-neutral-200); 16 | 17 | animation: rotate 1s infinite linear; /* global animation */ 18 | 19 | position:relative; 20 | inline-size:var(--p-loader-size); block-size:var(--p-loader-size); 21 | border:solid var(--p-loader-border-size) hsl(var(--p-loader-border-base-color)); 22 | border-radius: var(--border-radius-circular); 23 | border-block-start-color:hsl(var(--p-loader-base-full-color)); border-inline-start-color:hsl(var(--p-loader-base-full-color)); 24 | svg { inline-size:100%; block-size:100%; } 25 | &.is-loading { 26 | animation:none; 27 | border-block-start-color: hsl(var(--p-loader-border-base-color)); 28 | border-inline-start-color: hsl(var(--p-loader-border-base-color)); 29 | &::before { 30 | content:""; display:flex; 31 | position:absolute; inset:calc(var(--p-loader-border-size) * -1); 32 | inline-size:calc(100% + var(--p-loader-border-size)*2); 33 | block-size:calc(100% + var(--p-loader-border-size)*2); 34 | border-radius:var(--border-radius-circular); 35 | background:conic-gradient(hsl(var(--p-loader-base-full-color)) 0deg, hsl(var(--p-loader-base-full-color)) var(--loading), transparent var(--loading), transparent 360deg); 36 | } 37 | &::after { 38 | content:""; display:block; 39 | position:absolute; inset:0; 40 | inline-size:100%; block-size:100%; 41 | border-radius:var(--border-radius-circular); 42 | background: hsl(var(--p-loader-bg-color)); 43 | } 44 | } 45 | &.is-transparent { --p-loader-base-full-color:var(--transparent)!important; } 46 | 47 | &.is-small { 48 | --p-loader-size: var(--loader-size, #{pxToRem(16)}); 49 | --p-loader-border-size: var(--loader-border-size, #{pxToRem(1.5)}); 50 | } 51 | 52 | /* Theme Dark */ 53 | #{$theme-dark} & { 54 | --p-loader-border-base-color: var(--color-neutral-20); 55 | --p-loader-base-full-color: var(--color-neutral-100); 56 | --p-loader-bg-color-default: var(--p-loader-bg-color-dark); 57 | } 58 | } -------------------------------------------------------------------------------- /src/styles/7-components/_collapsible.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .collapsible { 3 | --p-toggle-border-color: var(--color-neutral-10); 4 | --p-toggle-optional-color: var(--color-neutral-50); 5 | 6 | ::-webkit-details-marker { display:none; } 7 | 8 | &-item { 9 | &:where( :not(:last-child) ) { border-block-end:solid pxToRem(1) hsl(var(--p-toggle-border-color)); } 10 | /* state */ 11 | &.is-info { 12 | --p-bg-color-info-focus-hover-opened: var(--color-neutral-5); 13 | --color-border: var(--color-neutral-10); 14 | .collapsible-wrapper { 15 | padding:pxToRem(8); margin-block:pxToRem(8); 16 | border-radius:var(--border-radius-small); 17 | &:has(:hover), 18 | &:where([open]) { background-color:hsl(var(--p-bg-color-info-focus-hover-opened)); } 19 | &.is-disabled { background-color:transparent; opacity:0.4; } 20 | .collapsible-button { 21 | padding-block:0; 22 | .icon:last-child { margin-inline-end:pxToRem(8); } 23 | } 24 | .collapsible-content { padding-block-end:pxToRem(8); } 25 | &:has(:focus-visible) { 26 | box-shadow:var(--focus-box-shadow); 27 | .collapsible-button { 28 | &:focus-visible { box-shadow:none; } 29 | } 30 | } 31 | #{$theme-dark} & { 32 | --p-bg-color-info-focus-hover-opened: var(--color-neutral-85); 33 | --color-border: var(--color-neutral-80); 34 | } 35 | } 36 | } 37 | } 38 | 39 | /* logic */ 40 | &-wrapper { 41 | padding:pxToRem(8); 42 | &:where([open]):not(#{$disabled}) { 43 | .icon-cheveron-right { rotate:90deg; } 44 | .icon-cheveron-down { rotate:180deg; } 45 | } 46 | &:is(#{$disabled}) { 47 | cursor:not-allowed; 48 | * { cursor:not-allowed; } 49 | .collapsible { 50 | &-content { display:none!important; } 51 | } 52 | } 53 | } 54 | 55 | &-button { 56 | position:relative; padding-block:pxToRem(10); 57 | display:flex; gap:pxToRem(10); align-items:center; font-size:pxToRem(16); line-height:1.5; 58 | .text { align-self:center; font-weight:600; } 59 | .icon { align-self:center; } 60 | [class*="icon-"] { display:block; transition:var(--transition); } 61 | .icon:first-child { margin-inline-end:pxToRem(8); } 62 | .icon:last-child { margin-inline-start:auto; } 63 | &-optional { font-size:pxToRem(13); color:hsl(var(--p-toggle-optional-color)); } 64 | &:where(summary) { cursor:pointer; } 65 | } 66 | 67 | &-content { 68 | padding-block-start:0; padding-block-end:pxToRem(24); 69 | } 70 | #{$theme-dark} & { 71 | --p-toggle-border-color: var(--color-neutral-80); 72 | } 73 | } -------------------------------------------------------------------------------- /src/assets/astro.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/styles/7-components/_upload-box.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .upload-box { 3 | --p-header-text-color: var(--color-neutral-70); 4 | --p-header-bg-color: var(--color-neutral-10); 5 | 6 | --p-content-text-color: var(--color-neutral-60); 7 | --p-content-bg-color: var(--color-neutral-0); 8 | 9 | --p-border-color: var(--color-neutral-10); 10 | 11 | overflow:hidden; min-inline-size:pxToRem(285); 12 | box-shadow:var(--shadow-small); 13 | border-radius:var(--border-radius-small); 14 | font-size:pxToRem(14); line-height:1; 15 | 16 | &-button { 17 | $size: #{pxToRem(20)}; 18 | --p-icon-button-size:var(--icon-button-size, #{$size}); 19 | 20 | inline-size: var(--p-icon-button-size); 21 | block-size: var(--p-icon-button-size); 22 | font-size: var(--p-icon-button-size); 23 | transition: var(--transition); 24 | 25 | line-height:1; text-align:center; flex-shrink:0; cursor:pointer; 26 | 27 | &.is-open { transform:rotate(180deg); } 28 | &.is-success { color:var(--config-color-success); } 29 | } 30 | &-header { 31 | display:flex; padding:pxToRem(16); 32 | color:hsl(var(--p-header-text-color)); background-color:hsl(var(--p-header-bg-color)); 33 | .upload-box-button { margin-inline-start:pxToRem(16); } 34 | } 35 | &-title { 36 | align-self:center; margin-inline-end:auto; 37 | .text { text-transform:uppercase; letter-spacing:0.12em; } 38 | .amount { 39 | &::before { content:"("; } 40 | &::after { content:")"; } 41 | } 42 | } 43 | &-content { 44 | @include scroll; 45 | background-color:hsl(var(--p-content-bg-color)); color:hsl(var(--p-content-text-color)); 46 | block-size:0; overflow:auto; 47 | transition:var(--transition); 48 | &.is-open {block-size:auto; max-block-size:pxToRem(218); /* consider to change to rem */} 49 | } 50 | &-list { } 51 | &-item { 52 | display:flex; align-items:center; gap:pxToRem(16); padding:pxToRem(16) pxToRem(24); 53 | .file-name { @include trim; line-height:1.2; align-self:center; margin-inline-end:auto; } 54 | &-button { align-self:center; margin-inline-start:pxToRem(16);} 55 | .icon-check { color:hsl(var(--color-text-success)); } 56 | &:not(:last-child) { border-bottom:solid pxToRem(1) hsl(var(--p-border-color)); } 57 | } 58 | 59 | /* states */ 60 | &.is-float { 61 | position:fixed; 62 | @media #{$break1} { inset-inline:pxToRem(16); inset-block-end:pxToRem(20); } 63 | @media #{$break2open} { inset-inline-end:pxToRem(24); inset-block-end:pxToRem(24); } 64 | } 65 | 66 | /* dark theme */ 67 | #{$theme-dark} &{ 68 | --p-header-text-color: var(--color-neutral-20); 69 | --p-header-bg-color: var(--color-neutral-100); 70 | 71 | --p-content-text-color: var(--color-neutral-20); 72 | --p-content-bg-color: var(--color-neutral-90); 73 | 74 | --p-border-color: var(--color-neutral-85); 75 | } 76 | } -------------------------------------------------------------------------------- /src/styles/7-components/_alert-sticky.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .alert-sticky { 4 | $width-alert: pxToRem(440); 5 | --p-alert-sticky-width-size: #{$width-alert}; 6 | 7 | --p-alert-content-text-color: var(--color-neutral-70); 8 | --p-alert-content-bg-color: var(--color-neutral-0); 9 | --p-alert-content-border-color: var(--color-neutral-10); 10 | 11 | /** type of messages colors **/ 12 | --p-alert-bg-color: var(--p-alert-bg-color-default); 13 | /* default */ 14 | --p-alert-bg-color-default: var(--color-neutral-20); 15 | /* info */ 16 | --p-alert-bg-color-info: var(--color-information-100); 17 | /* success */ 18 | --p-alert-bg-color-success: var(--color-success-100); 19 | /* warning */ 20 | --p-alert-bg-color-warning: var(--color-warning-100); 21 | /* danger */ 22 | --p-alert-bg-color-danger: var(--color-danger-100); 23 | 24 | position: relative; 25 | display: grid; 26 | grid-template-columns: pxToRem(72) 1fr; 27 | grid-template-areas: "image content" 28 | "image buttons"; 29 | 30 | inline-size: var(--p-alert-sticky-width-size); /* request of Chen */ 31 | font-size: var(--font-size-0); 32 | color: hsl(var(--p-alert-content-text-color)); 33 | border: solid pxToRem(1) hsl(var(--p-alert-content-border-color)); 34 | border-radius: var(--border-radius-xsmall); 35 | box-shadow: var(--shadow-large); 36 | user-select: none; 37 | 38 | > .button { position:absolute; inset-inline-end:pxToRem(16); inset-block-start:pxToRem(16); } 39 | &-image { 40 | grid-area: image; 41 | display:grid; place-content:center; margin:pxToRem(-1); margin-inline-end:0; 42 | background-color:hsl(var(--p-alert-bg-color)); border-start-start-radius:inherit; border-end-start-radius:inherit; 43 | color:hsl(var(--color-neutral-0)); font-size:pxToRem(24); 44 | [class^=icon-], 45 | [class*=" icon-"]{ font-size:var(--icon-size-large); } 46 | } 47 | &-content { 48 | grid-area:content; 49 | flex:1; background-color:hsl(var(--p-alert-content-bg-color)); 50 | padding:pxToRem(16); padding-block-end:0; padding-inline-end:pxToRem(48); border-start-end-radius:inherit; 51 | &:last-child { padding-block-end:pxToRem(16); } 52 | } 53 | &-buttons { grid-area:buttons; background-color:hsl(var(--p-alert-content-bg-color)); padding-block-end:pxToRem(8); border-end-end-radius:inherit;} 54 | &-title { font-size:var(--font-size-0); font-weight:600; margin-bottom:pxToRem(4); } 55 | 56 | /* alert types */ 57 | &.is-info { --p-alert-bg-color:var(--p-alert-bg-color-info); } 58 | &.is-success { --p-alert-bg-color:var(--p-alert-bg-color-success); } 59 | &.is-warning { --p-alert-bg-color:var(--p-alert-bg-color-warning); } 60 | &.is-danger { --p-alert-bg-color:var(--p-alert-bg-color-danger); } 61 | 62 | #{$theme-dark} & { 63 | --p-alert-content-text-color: var(--color-neutral-10); 64 | --p-alert-content-bg-color: var(--color-neutral-85); 65 | --p-alert-content-border-color: var(--color-neutral-80); 66 | } 67 | 68 | @media #{$break1} { 69 | --p-alert-sticky-width-size: auto; 70 | } 71 | } -------------------------------------------------------------------------------- /src/styles/6-elements/form/_switch.scss: -------------------------------------------------------------------------------- 1 | @use '../../abstract' as *; 2 | .switch { 3 | 4 | --p-switch-bg-color: var(--p-switch-bg-color-default); 5 | --p-switch-bg-color-default: var(--color-neutral-0); 6 | --p-switch-bg-color-disabled: var(--p-switch-bg-color-default); 7 | 8 | --p-bg-color: var(--p-bg-color-default); 9 | --p-bg-color-default: var(--color-neutral-20); 10 | 11 | --p-bg-color-checked: var(--color-information-100); 12 | 13 | --p-bg-color-hover: var(--color-neutral-20); 14 | --p-bg-color-checked-hover: var(--color-information-100); 15 | 16 | --p-bg-color-active: var(--color-neutral-60); 17 | --p-bg-color-checked-active: var(--color-information-120); 18 | 19 | --p-bg-color-disabled: var(--color-neutral-15); 20 | --p-bg-color-checked-disabled: var(--color-information-50); 21 | 22 | 23 | all:unset; position:relative; display:inline-flex; box-sizing:border-box; flex-shrink:0; 24 | inline-size:pxToRem(36); block-size:pxToRem(20); border-radius:var(--border-radius-medium); 25 | padding:pxToRem(2); background-color:hsl(var(--p-bg-color)); 26 | cursor:pointer; transition:var(--transition); 27 | &::before { 28 | content:""; position:absolute; inset-inline-start:pxToRem(2); 29 | display:block; inline-size:pxToRem(16); block-size:pxToRem(16); 30 | background-color:hsl(var(--p-switch-bg-color)); border-radius:var(--border-radius-circular); 31 | box-shadow:var(--shadow-small); transition:var(--transition); 32 | } 33 | /* give back after reset */ 34 | &:where(:focus-visible) { 35 | box-shadow: var(--focus-box-shadow); 36 | } 37 | 38 | /* states */ 39 | &.is-small { 40 | inline-size:pxToRem(30); block-size:pxToRem(16); 41 | &::before{ inline-size:pxToRem(12); block-size:pxToRem(12);} 42 | &:where(:checked)::before { transform:translateX(calc( pxToRem(14) * var(--transform-direction) )); } 43 | } 44 | 45 | &.is-large { 46 | inline-size:pxToRem(40); block-size:pxToRem(24); 47 | &::before{ inline-size:pxToRem(20); block-size:pxToRem(20);} 48 | &:where(:checked)::before { transform:translateX(calc(pxToRem(16) * var(--transform-direction) )); } 49 | } 50 | 51 | &:where(:focus) { 52 | $focus: 0 0 0 pxToRem(1) hsl(var(--color-information-100)), 0 0 0 pxToRem(2) hsl(var(--color-information-100) / 0.25); 53 | --focus-box-shadow: #{$focus}; 54 | } 55 | 56 | &:where(:checked) { 57 | --p-bg-color: var(--p-bg-color-checked); 58 | &::before { transform:translateX(calc(pxToRem(16) * var(--transform-direction))); } 59 | } 60 | &:where(:hover) { 61 | --p-bg-color: var(--p-bg-color-hover); 62 | &:where(:checked) { --p-bg-color: var(--p-bg-color-checked-hover); } 63 | } 64 | &:where(:active) { 65 | --p-bg-color: var(--p-bg-color-active); 66 | &:where(:checked) { --p-bg-color: var(--p-bg-color-checked-active); } 67 | } 68 | &:where(:disabled) { 69 | --p-bg-color: var(--p-bg-color-disabled); 70 | --p-switch-bg-color: var(--p-switch-bg-color-disabled); 71 | cursor: default; 72 | &:where(:checked) { --p-bg-color: var(--p-bg-color-checked-disabled); } 73 | } 74 | 75 | 76 | #{$theme-dark} & { 77 | --p-switch-bg-color-disabled: var(--color-neutral-70); 78 | --p-bg-color-disabled: var(--color-neutral-85); 79 | --p-bg-color-checked-disabled: var(--color-information-200); 80 | } 81 | } -------------------------------------------------------------------------------- /src/layouts/Layout.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import "../styles/theme.scss"; 3 | import "../styles/global.css"; 4 | import "../styles/custom.scss"; 5 | 6 | const pathname: string = Astro.url.pathname; 7 | --- 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Astro Basics 16 | 17 | 18 | 19 | 24 | 25 |
26 | 27 | 66 | 67 | 68 |
69 | 70 | 87 | 88 | 89 |
90 |
91 | 92 | 93 | 94 | 122 | -------------------------------------------------------------------------------- /src/pages/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../layouts/Layout.astro"; 3 | import can from "../sdk/abstract"; 4 | --- 5 | 6 | 7 |
8 |
9 |

Dashboard

10 |

Welcome to the homepage.

11 |
12 | 13 |
14 |
15 |
16 |

19 | 20 | 26 | 27 | 30 | 35 | 36 | 37 | 38 | Applications 39 |

40 |
41 |
42 |
43 |

44 | {12} 45 |

46 |

Applications

47 |
48 |
49 |

Running: {7}

50 |
51 |
52 |
53 | 54 |
55 |
56 |

59 | 60 | 66 | 73 | 74 | 75 | Users 76 |

77 |
78 |
79 |
80 |

81 | 4 82 |

83 |

Users

84 |
85 |
86 |

Admin(s): {1}

87 |
88 |
89 |
90 |
91 |
92 |
93 | -------------------------------------------------------------------------------- /src/styles/7-components/_alert.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .alert { 4 | --p-alert-text-color: var(--color-neutral-70); 5 | --p-alert-bg-color: var(--color-neutral-5); 6 | --p-alert-border-color: var(--color-neutral-15); 7 | 8 | /* states colors */ 9 | --p-alert-color: var(--p-alert-color-default); 10 | 11 | --p-alert-color-default: var(--color-neutral-20); 12 | --p-alert-color-info: var(--color-information-100); 13 | --p-alert-color-success: var(--color-success-100); 14 | --p-alert-border-warning: var(--color-warning-100); 15 | --p-alert-border-danger: var(--color-danger-100); 16 | 17 | /*** End inner variables */ 18 | 19 | /* use inner variables */ 20 | color: hsl(var(--p-alert-text-color)); 21 | background-color: hsl(var(--p-alert-bg-color)); 22 | border: solid pxToRem(1) hsl(var(--p-alert-border-color)); 23 | 24 | /* other styles */ 25 | padding: pxToRem(12); 26 | padding-inline-start: pxToRem(8); 27 | border-radius: var(--border-radius-xsmall); 28 | 29 | &-grid { 30 | display: flex; 31 | gap: pxToRem(16); 32 | &::before { 33 | content:""; display:block; inline-size:pxToRem(2); 34 | background-color:hsl(var(--p-alert-color)); border-radius:pxToRem(1); 35 | } 36 | > [class*="icon-"]:where(:not(.icon-x)) { color:hsl(var(--p-alert-color)); font-size:var(--icon-size-large); line-height:1.25; } 37 | > .button { order: 1; } 38 | } 39 | 40 | &-content { display:flex; flex-direction:column; gap:pxToRem(8); flex:1; line-height:1.5; } 41 | &-title { font-weight:bold; } 42 | &-message { } 43 | &-buttons { margin-block-start:pxToRem(12); margin-inline-start:pxToRem(-16); } 44 | 45 | .button { --button-size:1.25rem; font-size:var(--font-size-0); } 46 | 47 | /* alert layout state */ 48 | &.is-action { 49 | position:relative; padding:pxToRem(16); padding-block-start:pxToRem(18); 50 | border-width:0; border-radius:0; 51 | .alert-buttons { display:flex; flex-wrap:wrap; margin-block-start:0; margin-inline-start:0; } 52 | .button { --button-size:2.5rem; } 53 | .alert-grid { 54 | flex-wrap:wrap; 55 | &::before { 56 | position:absolute; inset-inline:0; inset-block-start:0; border-radius:0; 57 | block-size:pxToRem(4); inline-size:100%; 58 | } 59 | } 60 | 61 | &-and-top-sticky { 62 | --p-alert-bg-color: var(--color-neutral-0); 63 | // #{$theme-dark} & { --p-alert-bg-color: var(--color-neutral-0); } 64 | } 65 | @media #{$break1} { 66 | .alert-buttons { flex-direction:column; inline-size:100%; } 67 | } 68 | } 69 | &.is-standalone { 70 | --p-alert-bg-color: var(--color-neutral-0); 71 | --p-alert-border-color: var(--color-neutral-10); 72 | box-shadow: var(--shadow-small); 73 | #{$theme-dark} & { 74 | --p-alert-bg-color: var(--color-neutral-90); 75 | --p-alert-border-color: var(--color-neutral-85); 76 | } 77 | } 78 | 79 | /* alert types (colors) */ 80 | &.is-info { --p-alert-color:var(--p-alert-color-info); } 81 | &.is-success { --p-alert-color:var(--p-alert-color-success); } 82 | &.is-warning { --p-alert-color:var(--p-alert-border-warning); } 83 | &.is-danger { --p-alert-color:var(--p-alert-border-danger); } 84 | 85 | &.is-no-bg { border-width:0; background-color:hsl(var(--transparent)); } 86 | 87 | #{$theme-dark} & { 88 | --p-alert-text-color: var(--color-neutral-5); 89 | --p-alert-bg-color: var(--color-neutral-85); 90 | --p-alert-border-color: var(--color-neutral-80); 91 | } 92 | } -------------------------------------------------------------------------------- /src/styles/7-components/_side-nav.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .side-nav { 4 | --p-side-nav-bg-color: var(--color-neutral-0); 5 | --p-side-nav-border-color: var(--color-border); 6 | 7 | --p-side-nav-header-text-color: var(--color-neutral-50); 8 | 9 | background-color: hsl(var(--p-side-nav-bg-color)); 10 | border-inline-end: solid pxToRem(1) hsl(var(--p-side-nav-border-color)); 11 | 12 | &-level-1, 13 | &-level-2 { display:flex; flex-direction:column; } 14 | 15 | &-level-1 { 16 | position:relative; transition:var(--transition); 17 | &.is-narrow { 18 | @media #{$break3open} { 19 | inline-size: pxToRem(72); 20 | .drop-section { padding-inline-end:pxToRem(16); } 21 | } 22 | } 23 | } 24 | &-level-2 { 25 | display:none; border-inline-start:solid pxToRem(1) hsl(var(--color-border)); 26 | &.is-open { display:flex; } 27 | } 28 | 29 | &-top { } 30 | &-main { 31 | flex:1; overflow-y:auto; 32 | @include scroll(); scrollbar-gutter:initial; 33 | overflow: overlay; // fallback macOS 34 | overflow-x: hidden; 35 | 36 | &:not(:hover) { 37 | &::-webkit-scrollbar-thumb { 38 | background: hsl(var(--transparent)); 39 | } 40 | 41 | &::-webkit-scrollbar-corner { 42 | background: hsl(var(--transparent)); 43 | } 44 | } 45 | } 46 | &-bottom { } 47 | 48 | /* override drop partial */ 49 | .drop { 50 | &-section { 51 | $padding-horizontal: pxToRem(16); 52 | $padding-vertical: pxToRem(24); 53 | --section-padding-horizontal: #{$padding-horizontal}; 54 | --section-padding-vertical: #{$padding-vertical}; 55 | } 56 | &-list { } 57 | &-button { 58 | $padding-horizontal: pxToRem(12); 59 | $padding-vertical: pxToRem(8); 60 | --button-padding-horizontal: #{$padding-horizontal}; 61 | --button-padding-vertical: #{$padding-vertical}; 62 | 63 | line-height: 1.7145; 64 | .text { @include trim(1); } 65 | } 66 | } 67 | &-button { 68 | position:absolute; inset-inline-end:pxToRem(-16); inset-block-end:pxToRem(28); 69 | display:grid; place-content:center; padding-inline:0; inline-size:pxToRem(32); 70 | border-radius:var(--border-radius-small); 71 | .icon-cheveron-right { display:block; transition:var(--transition);} 72 | &.is-open { 73 | .icon-cheveron-right { transform:rotateZ(180deg); } 74 | } 75 | } 76 | .collapsible-wrapper { padding:0; } 77 | .eyebrow-heading-3 { color: var(--p-side-nav-header-text-color); } 78 | 79 | #{$theme-dark} & { 80 | --p-side-nav-bg-color: var(--color-neutral-105); 81 | 82 | --p-side-nav-header-text-color: var(--color-neutral-20); 83 | } 84 | @media #{$break1}, #{$break2} { 85 | &.is-mobile-center { 86 | .drop { 87 | &-list { 88 | &-item { 89 | display:flex; justify-content:center; 90 | } 91 | } 92 | &-button { 93 | justify-content:center; 94 | [class*="icon"] { display:none; } 95 | } 96 | } 97 | } 98 | 99 | .side-nav-level-1 { display:block; } 100 | .side-nav-level-2 { display:none; } 101 | &.is-open-level-2 { 102 | .side-nav-level-1 { display:none; } 103 | .side-nav-level-2 { display:block; } 104 | } 105 | } 106 | @media #{$break3open} { 107 | display:flex; block-size:100%; 108 | 109 | &-level-1, 110 | &-level-2 { inline-size:pxToRem(200); } 111 | 112 | .drop-section { margin-inline:0; } 113 | } 114 | } -------------------------------------------------------------------------------- /src/styles/2-resets/_typography.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | /* remove bounce affect on Safari mac */ 4 | html, body { 5 | overscroll-behavior-y: none; 6 | } 7 | 8 | html { 9 | //@include scroll(); //Eldad ask to try to use if without for MacOS affect (hide when not being use) 10 | scrollbar-gutter: stable; 11 | overflow: overlay; // fallback macOS 12 | overflow-x: hidden; 13 | &:has(:where(body#{$theme-dark})) { color-scheme:dark; } 14 | } 15 | 16 | body { 17 | --p-body-text-color: var(--color-neutral-60); 18 | --p-body-bg-color: var(--color-neutral-5); 19 | font-family: var(--content-font); 20 | -webkit-font-smoothing: antialiased; 21 | font-weight: 400; 22 | font-size: 87.5%; /* default equal to 14px */ 23 | line-height: 1.5; 24 | color: hsl(var(--p-body-text-color)); 25 | background-color: hsl(var(--p-body-bg-color)); 26 | 27 | &#{$theme-dark} { 28 | --p-body-text-color: var(--color-neutral-20); 29 | --p-body-bg-color: var(--color-neutral-105); 30 | } 31 | } 32 | 33 | /* 34 | Native element affect 35 | 36 | there also utilities classes: 37 | - u-small-text 38 | - u-font-bold 39 | */ 40 | small { font-size:pxToRem(14); } 41 | b { font-weight:600; } 42 | code { 43 | font-family: var(--code-font); 44 | font-size: pxToRem(14); 45 | line-height: 1.5; 46 | letter-spacing: 0.08em; 47 | white-space: pre-wrap; 48 | } 49 | 50 | /** heading **/ 51 | 52 | /* color for both heading */ 53 | [class*="heading-"] { 54 | --p-heading-text-color: var(--heading-text-color, var(--color-neutral-80)); 55 | color: hsl(var(--p-heading-text-color)); 56 | #{$theme-dark} & { 57 | --p-heading-text-color: var(--heading-text-color, var(--color-neutral-10)); 58 | } 59 | } 60 | 61 | [class*="heading-level"] { 62 | font-family: var(--heading-font, arial); 63 | line-height: 1.5; 64 | } 65 | 66 | .heading-level { 67 | @media #{$break1}, #{$break2} { 68 | &-1 { font-size:var(--font-size-7); font-weight:700; } 69 | &-2 { font-size:var(--font-size-6); font-weight:700; } 70 | &-3 { font-size:var(--font-size-5); font-weight:600; } 71 | &-4 { font-size:var(--font-size-4); font-weight:500; } 72 | &-5 { font-size:var(--font-size-3); font-weight:500; } 73 | &-6 { font-size:var(--font-size-2); font-weight:500; } 74 | &-7 { font-size:var(--font-size-1); font-weight:500; } 75 | } 76 | @media #{$break3open} { 77 | &-1 { font-size:var(--font-size-8); font-weight:700; } 78 | &-2 { font-size:var(--font-size-7); font-weight:700; } 79 | &-3 { font-size:var(--font-size-6); font-weight:700; } 80 | &-4 { font-size:var(--font-size-5); font-weight:600; } 81 | &-5 { font-size:var(--font-size-4); font-weight:500; } 82 | &-6 { font-size:var(--font-size-3); font-weight:500; } 83 | &-7 { font-size:var(--font-size-2); font-weight:500; } 84 | } 85 | } 86 | 87 | [class*="eyebrow-heading"] { 88 | text-transform: uppercase; 89 | font-weight: 600; 90 | line-height: 1.5; 91 | } 92 | 93 | .eyebrow-heading { 94 | &-1 { font-size:var(--font-size-1); letter-spacing:0.08em; } 95 | &-2 { font-size:var(--font-size-0); letter-spacing:0.08em; } 96 | &-3 { font-size:var(--font-size-00); letter-spacing:0.12em; } 97 | } 98 | 99 | .body-text { 100 | &-1 { font-size:var(--font-size-1); } 101 | &-2 { font-size:var(--font-size-0); } 102 | } 103 | 104 | ::selection { 105 | color: hsl(var(--color-neutral-1000)); -webkit-text-fill-color: hsl(var(--color-neutral-1000)); 106 | background-color: hsl(var(--color-mint-500)); background-clip:revert; -webkit-background-clip:revert; 107 | } 108 | 109 | :where(body) :focus-visible { 110 | /* focus styles */ 111 | box-shadow: var(--focus-box-shadow); 112 | } -------------------------------------------------------------------------------- /src/styles/8-grids/_wizard.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract/index' as *; 2 | 3 | .wizard { 4 | --p-header-color: var(--color-neutral-0); 5 | --p-start-color: var(--color-neutral-5); 6 | --p-end-color: var(--color-neutral-0); 7 | 8 | $header-height: pxToRem(64); 9 | --p-header-height: #{$header-height}; 10 | 11 | 12 | /* bg layout */ 13 | &-header-strip { background-color:hsl(var(--p-header-color)); border-block-end:solid pxToRem(1) hsl(var(--color-border)); } 14 | &-start-bg { } 15 | &-end-bg { background-color:hsl(var(--p-end-color)); } 16 | 17 | /* content layout */ 18 | &-header { padding-inline:pxToRem(32); } 19 | &-side { padding-inline:pxToRem(32); } 20 | &-main { padding-inline:pxToRem(32); } 21 | &-media { } 22 | 23 | 24 | /* content layout */ 25 | &-header-strip { position:sticky; z-index:2; inset-block-start:0; } 26 | &-header { 27 | position:sticky; z-index:2; inset-block-start:0; 28 | display:flex; align-items:center; gap:pxToRem(12); 29 | } 30 | &-side { align-self:start; } 31 | &-media { 32 | display:grid; justify-content:center; align-items:end; position:relative; 33 | > * { position:sticky; inset-inline:pxToRem(32); inset-block-end:pxToRem(32); margin-inline:auto; max-inline-size:calc(100% - 64px); max-block-size:320px; } 34 | @media (max-height:860px) { display:none; } 35 | } 36 | &-main { display:flex; flex-direction:column; padding-block-start:pxToRem(40); padding-inline:pxToRem(40); min-inline-size:0; } 37 | .form { 38 | block-size:100%; max-block-size:100%; 39 | &-footer { 40 | position:sticky; inset-block-end:0; 41 | background-color: hsl(var(--p-end-color)); 42 | } 43 | } 44 | 45 | @media #{$break1} { 46 | display: grid; 47 | grid-template-rows: var(--p-header-height); 48 | min-block-size: 100dvh; 49 | &-header-strip, 50 | &-header { padding-inline:pxToRem(16); grid-row:1; grid-column:1; } 51 | .form-footer { padding-inline:pxToRem(40); margin-inline:pxToRem(-16); } 52 | 53 | &-side { 54 | display:none; padding:pxToRem(16); 55 | &.is-shown-mobile { display:block; } 56 | } 57 | &-main { padding:pxToRem(16); padding-block-end:0; background-color:hsl(var(--p-end-color)); } 58 | &-media { display:none; } 59 | &-start-bg, 60 | &-end-bg { display:none; } 61 | } 62 | @media #{$break2open} { 63 | display: grid; 64 | grid-template-columns: 1fr minmax(pxToRem(240),pxToRem(330)) minmax(pxToRem(0), pxToRem(100)) minmax(pxToRem(480),pxToRem(750)) 1fr; 65 | grid-auto-rows: var(--p-header-height) auto 1fr; 66 | min-block-size: 100vh; 67 | 68 | &.is-no-gap-middle { grid-template-columns: 1fr minmax(pxToRem(240),pxToRem(330)) 0 minmax(pxToRem(480),pxToRem(750)) 1fr; } 69 | 70 | &-side { position:sticky; z-index:2; inset-block-start:var(--p-header-height); padding-block-start:pxToRem(54); } 71 | 72 | /* bg layout */ 73 | &-header-strip { grid-row:1; grid-column:1 / -1; } 74 | &-start-bg { grid-row:2 / 4; grid-column:1 / 3; background-color:hsl(var(--p-start-color)); border-inline-end:solid pxToRem(1) hsl(var(--color-border));} 75 | &-end-bg { grid-row:2 / 4; grid-column:3 / 6; } 76 | 77 | /* content layout */ 78 | &-header { grid-row:1; grid-column:2 / 5; } 79 | &-side { grid-row:2; grid-column:2; } 80 | &-main { grid-row:2 / 4; grid-column:4; } 81 | &-media { grid-row:3; grid-column:1 / 3; } 82 | 83 | /* full layout */ 84 | &.is-full-center-layout { 85 | .wizard-container { 86 | grid-column:2 / 5; padding-inline:pxToRem(32); 87 | } 88 | } 89 | } 90 | 91 | 92 | #{$theme-dark} & { 93 | --p-header-color: var(--color-neutral-105); 94 | --p-start-color: var(--color-neutral-100); 95 | --p-end-color: var(--color-neutral-90); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/styles/6-elements/_card.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .card { 3 | --p-card-bg-color: var(--p-card-bg-color-default); 4 | --p-card-bg-color-default: var(--card-bg-color , var(--color-neutral-0)); 5 | --p-card-bg-color-hover: var(--color-neutral-5); 6 | 7 | --p-card-border-color: var(--p-card-border-color-default); 8 | --p-card-border-color-default: var(--color-border); 9 | --p-card-border-color-hover: var(--color-neutral-15); 10 | 11 | --p-card-border-radius: var(--card-border-radius, var(--border-radius-medium)); 12 | 13 | $padding: pxToRem(32); 14 | --p-card-padding: var(--card-padding, #{$padding}); 15 | 16 | position:relative; display:block; 17 | transition: var(--transition) background-color; 18 | background: hsl(var(--p-card-bg-color)); 19 | border-radius: var(--p-card-border-radius); 20 | box-shadow: var(--shadow-small); 21 | padding: var(--p-card-padding); 22 | border: solid pxToRem(1) hsl(var(--p-card-border-color)); 23 | 24 | &-header { 25 | min-block-size:pxToRem(210); padding:var(--p-card-padding); margin:calc(var(--p-card-padding) * -1); 26 | border-start-start-radius:inherit; border-start-end-radius:inherit; overflow:hidden; 27 | background:linear-gradient(271.77deg, #FCFCFF 0%, #FDFDFF 82.19%, #FFFFFF 99.87%); 28 | #{$theme-dark} & { background:linear-gradient(96.46deg, #1B1B28 8.56%, #282A3B 115.77%); } 29 | 30 | &-image { margin:calc(var(--p-card-padding) * -1); max-block-size:pxToRem(178); margin-inline-end:0; } 31 | } 32 | &:focus-visible { 33 | /* focus styles */ 34 | box-shadow: var(--focus-box-shadow); 35 | } 36 | &-separator { 37 | padding-block-start: var(--p-card-padding); 38 | padding-inline: var(--p-card-padding); 39 | margin-block-start: var(--p-card-padding); 40 | margin-inline: calc(var(--p-card-padding) * -1); 41 | border-block-start: solid pxToRem(1) hsl(var(--p-card-border-color)); 42 | } 43 | 44 | /* upload state */ 45 | &:where(a, button) { 46 | &:hover { 47 | --p-card-bg-color: var(--p-card-bg-color-hover); 48 | --p-card-border-color: var(--p-card-border-color-hover); 49 | } 50 | } 51 | &.is-border-dashed { border:dashed pxToRem(1) hsl(var(--p-card-border-color)); } 52 | //&.is-hover-with-file { --p-card-bg-color: var(--p-card-bg-color-hover-file); } 53 | 54 | &.is-no-shadow { box-shadow:none; } 55 | 56 | &.is-allow-focus { 57 | cursor: pointer; 58 | &:hover { 59 | --p-card-bg-color: var(--p-card-bg-color-hover); 60 | --p-card-border-color: var(--p-card-border-color-hover); 61 | } 62 | &:has(:focus-visible) { box-shadow:var(--focus-box-shadow); } 63 | } 64 | 65 | &.is-danger { 66 | &::before { 67 | position:absolute; inset-inline-start:pxToRem(12); inset-block:pxToRem(18); 68 | content:""; display:block; inline-size:pxToRem(2); border-radius:pxToRem(1); 69 | background-color:hsl(var(--color-text-danger)); 70 | } 71 | [class*="heading-level"] { color:hsl(var(--color-text-danger)); } 72 | .card-separator { padding-inline:0; margin-inline:0; } 73 | } 74 | 75 | #{$theme-dark} & { 76 | --p-card-bg-color-default: var(--color-neutral-90); 77 | --p-card-bg-color-hover: var(--color-neutral-85); 78 | --p-card-border-color-hover: var(--color-neutral-80); 79 | } 80 | 81 | @media #{$break1} { 82 | $padding: pxToRem(16); 83 | --p-card-padding: var(--card-padding-mobile, #{$padding}); 84 | } 85 | } 86 | 87 | .separator-with-text { 88 | --p-text-color: var(--color-neutral-20); 89 | display:flex; gap:pxToRem(16); align-items:center; margin-block:pxToRem(48); 90 | color:hsl(var(--p-text-color)); font-size:var(--font-size-00); line-height:1; 91 | 92 | &::before, 93 | &::after { content:""; display:block; flex:1; block-size:0; border-block-start:solid pxToRem(1) hsl(var(--color-border)); } 94 | 95 | #{$theme-dark} & { 96 | --p-text-color: var(--color-neutral-50); 97 | } 98 | } -------------------------------------------------------------------------------- /src/sdk/index.ts: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import CoreAbstraction, { clients } from "./core"; 3 | import { Engine } from "./enums"; 4 | 5 | export interface BotData { 6 | // id: string; 7 | // name: string; 8 | // engine: Engine; 9 | // status: "running" | "stopped" | "error"; 10 | } 11 | 12 | enum UpdateStatusTypes { 13 | Start = 0, 14 | Stop = 1, 15 | Restart = 2 16 | } 17 | 18 | export interface UpdateStatusRequest { 19 | bot_id: string; 20 | status: UpdateStatusTypes; 21 | } 22 | 23 | export interface CreateBotOptions { 24 | name: string; 25 | engine: Engine; 26 | } 27 | 28 | export interface UpdateBotOptions extends CreateBotOptions { } 29 | 30 | export class Bot { 31 | public isRunning: boolean | null = null; 32 | public data: BotData; 33 | 34 | constructor(data: BotData) { 35 | this.data = data; 36 | } 37 | 38 | async initialize() { 39 | // Initialization logic 40 | } 41 | 42 | async update(newOptions: UpdateBotOptions) { 43 | // TODO: Send request to update bot 44 | } 45 | 46 | async start() { 47 | // TODO: Start bot logic 48 | } 49 | 50 | async stop() { 51 | // TODO: Stop bot logic 52 | } 53 | 54 | async restart() { 55 | // TODO: Restart bot logic 56 | } 57 | 58 | async is_running(): Promise { 59 | return this.isRunning ?? false; 60 | } 61 | } 62 | 63 | class Crabshell { 64 | core: CoreAbstraction 65 | constructor(address: string) { 66 | this.core = new CoreAbstraction(address) 67 | } 68 | 69 | async find_bot_by_id(botId: string): Promise { 70 | // TODO: Fetch bot data from backend 71 | return null; 72 | } 73 | 74 | async fetch_all_raw(): Promise { 75 | return await new Promise((resolve, reject) => { 76 | this.core.Clients.bot.ListAll({}, (error: Error, response: { data: any, [key: string]: any }) => { 77 | if (error) { 78 | reject(error); 79 | } else { 80 | resolve(response); 81 | } 82 | }); 83 | }); 84 | } 85 | 86 | async update_status_by_id(bot_id: string, status: UpdateStatusTypes) { 87 | const request: UpdateStatusRequest = { 88 | bot_id, 89 | status 90 | } 91 | 92 | return new Promise((resolve, reject) => { 93 | clients.bot.updateStatus(request, (err, resp) => { 94 | if (err) { 95 | console.error("Error updating bot status:", err); 96 | return reject(err); 97 | } 98 | if (!resp) { 99 | console.error("No response received."); 100 | return reject(new Error("No response received.")); 101 | } 102 | 103 | try { 104 | resolve(resp); 105 | } catch (error) { 106 | console.error("Error processing response:", error); 107 | reject(error); 108 | } 109 | }); 110 | }); 111 | } 112 | 113 | async create(options: CreateBotOptions): Promise { 114 | return new Promise((resolve, reject) => { 115 | clients.bot.createBot(options, (err, resp) => { 116 | if (err) { 117 | console.error("Error creating bot:", err); 118 | return reject(err); 119 | } 120 | if (!resp) { 121 | console.error("No response received."); 122 | return reject(new Error("No response received.")); 123 | } 124 | 125 | try { 126 | resolve(new Bot(resp)); 127 | } catch (error) { 128 | console.error("Error processing response:", error); 129 | reject(error); 130 | } 131 | }); 132 | }); 133 | } 134 | } 135 | 136 | export default Crabshell; 137 | -------------------------------------------------------------------------------- /src/styles/7-components/_tabs.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .tabs { 4 | --p-tabs-text-color: var(--p-tabs-text-color-default); 5 | --p-tabs-text-color-default: var(--color-neutral-50); 6 | --p-tabs-text-color-hover: var(--color-neutral-80); 7 | --p-tabs-text-color-active: var(--color-neutral-80); 8 | --p-tabs-text-color-selected: var(--color-neutral-80); 9 | 10 | --p-tabs-bg-color: var(--p-tabs-bg-defalut); 11 | --p-tabs-bg-defalut: var(--transparent); 12 | --p-tabs-bg-color-hover: var(--color-neutral-10); 13 | 14 | --p-tabs-outline-color: var(--p-tabs-outline-color-default); 15 | --p-tabs-outline-color-default: var(--transparent); 16 | --p-tabs-outline-color-focus: var(--color-neutral-1000) / 0.16; 17 | 18 | --p-tabs-border-color: var(--p-tabs-border-color-default); 19 | --p-tabs-border-color-default: var(--transparent); 20 | --p-tabs-border-color-selected: var(--color-neutral-80); 21 | 22 | --tabs-shadow-color: var(--color-neutral-0); 23 | --tabs-button-arrow-color: var(--color-neutral-80); 24 | 25 | position:relative; 26 | 27 | &-button { 28 | position:relative; display:flex; align-items:center; 29 | padding-inline:pxToRem(4); padding-block:pxToRem(7); 30 | user-select:none; border-radius:pxToRem(10); 31 | 32 | color:hsl(var(--p-tabs-text-color)); 33 | background-color:hsl(var(--p-tabs-bg-color)); background-clip:padding-box; 34 | border:solid pxToRem(4) hsl(var(--p-tabs-outline-color)); 35 | 36 | 37 | .text { 38 | display:flex; align-items:center; padding-inline:pxToRem(12); inline-size:100%; 39 | } 40 | &::before { 41 | content:""; display:block; block-size:pxToRem(1); background-color:transparent; 42 | position:absolute; inset-inline:0; inset-block-end:pxToRem(-4); 43 | border-radius:var(--border-radius-xsmall); 44 | } 45 | &::after { 46 | content:""; display:block; border-radius:var(--border-radius-small); 47 | } 48 | &:where(:hover, &:focus) { 49 | box-shadow: none; 50 | } 51 | &:where(:hover):not(#{$disabled}) { 52 | --p-tabs-text-color: var(--p-tabs-text-color-hover); 53 | --p-tabs-bg-color: var(--p-tabs-bg-color-hover); 54 | } 55 | &:where(:focus-visible):not(#{$disabled}) { 56 | --p-tabs-outline-color: var(--p-tabs-outline-color-focus); 57 | } 58 | &:where(:active):not(#{$disabled}) { 59 | --p-tabs-text-color: var(--p-tabs-text-color-active); 60 | } 61 | &:where(#{$disabled}) { 62 | opacity: 0.4; 63 | } 64 | &:is(.is-selected) { 65 | --p-tabs-text-color: var(--p-tabs-text-color-selected); 66 | &::before{ background-color:hsl(var(--p-tabs-border-color-selected)); } 67 | } 68 | } 69 | 70 | &-list { 71 | display:flex; gap:pxToRem(16); overflow:auto; margin-block-end:pxToRem(-1); 72 | /* remove Scroll */ 73 | -ms-overflow-style:none;/* IE and Edge */ scrollbar-width:none;/* Firefox */ 74 | &::-webkit-scrollbar { display:none; } /* Webkit */ 75 | } 76 | &-item { } 77 | &-button-scroll { 78 | position:absolute; z-index:3; inset-block:0; 79 | display:flex; align-items:center; inline-size:pxToRem(80); block-size:100%; padding-block-end:pxToRem(5); opacity:0.4; transition:var(--transition); 80 | color:hsl(var(--tabs-button-arrow-color)); font-size:var(--font-size-3); 81 | > * { margin-inline:-3px; transform:scaleX(var(--transform-direction)); } 82 | &:where(:hover, :focus) { opacity:1; } 83 | &.is-start { 84 | inset-inline-start:0; 85 | background:linear-gradient(to right, hsl(var(--tabs-shadow-color)) 0%, hsl(var(--tabs-shadow-color) / 0) 100%); 86 | } 87 | &.is-end { 88 | inset-inline-end:0; justify-content:end; 89 | background:linear-gradient(to left, hsl(var(--tabs-shadow-color)) 0%, hsl(var(--tabs-shadow-color) / 0) 100%); 90 | } 91 | } 92 | 93 | #{$theme-dark} & { 94 | --p-tabs-text-color-hover: var(--color-neutral-10); 95 | --p-tabs-text-color-active: var(--color-neutral-10); 96 | --p-tabs-text-color-selected: var(--color-neutral-10); 97 | 98 | --p-tabs-bg-color-hover: var(--color-neutral-0) / 0.04; 99 | 100 | --p-tabs-outline-color-focus: var(--color-neutral-0) / 0.16; 101 | 102 | --p-tabs-border-color-selected: var(--color-neutral-10); 103 | 104 | --tabs-button-arrow-color: var(--color-neutral-20); 105 | 106 | --tabs-shadow-color: var(--color-neutral-100); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/styles/7-components/_steps.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .steps { 3 | --p-step-bullet-icon-color: var(--color-neutral-0); 4 | --p-step-bullet-content-color: var(--color-neutral-0); 5 | --p-step-bullet-padding-color: var(--color-neutral-0); 6 | --p-step-bullet-border-color: var(--color-neutral-20); 7 | 8 | --p-step-bullet-sep-color: var(--color-neutral-20); 9 | 10 | // Done step 11 | --p-step-bullet-icon-color-done: var(--color-neutral-0); 12 | --p-step-bullet-content-color-done: var(--color-neutral-20); 13 | --p-step-bullet-padding-color-done: var(--color-neutral-20); 14 | //--p-step-bullet-border-color-done: var(--color-neutral-50); 15 | 16 | // Current Step 17 | //--p-step-bullet-icon-color-current: var(--color-neutral-0); 18 | --p-step-bullet-content-color-current: var(--color-primary-100); 19 | //--p-step-bullet-padding-color-current:var(--color-neutral-0); 20 | --p-step-bullet-border-color-current: var(--color-primary-100); 21 | 22 | /* Color Text */ 23 | --p-step-text-color: var(--color-neutral-60); 24 | --p-step-text-color-done: var(--color-neutral-50); 25 | --p-step-text-color-current: var(--color-primary-100); 26 | 27 | --p-substep-text-color: var(--color-neutral-50); 28 | --p-substep-text-color-done: var(--color-neutral-50); 29 | --p-substep-text-color-current: var(--color-neutral-80); 30 | 31 | display:grid; 32 | &-item { 33 | position: relative; 34 | font-size: var(--font-size-1); 35 | color: hsl(var(--p-step-text-color)); 36 | 37 | [class*="heading"] { margin-block-start:pxToRem(12); margin-block-end:pxToRem(24); } 38 | .bullet { 39 | position:relative; inline-size:pxToRem(24); block-size:pxToRem(24); 40 | .icon-check { 41 | text-align:center; line-height:pxToRem(24); 42 | color: hsl(var(--p-step-bullet-icon-color)); 43 | } 44 | &::before { 45 | content:""; display:block; inline-size:pxToRem(24); block-size:pxToRem(24); flex-shrink:0; 46 | background-color: hsl(var(--p-step-bullet-content-color)); 47 | border: solid pxToRem(6) hsl(var(--p-step-bullet-padding-color)); 48 | box-shadow: 0 0 0 pxToRem(1) hsl(var(--p-step-bullet-border-color)) ; 49 | border-radius: var(--border-radius-circular); 50 | } 51 | &.is-done { 52 | --p-step-bullet-icon-color: var(--p-step-bullet-icon-color-done); 53 | --p-step-bullet-content-color: var(--p-step-bullet-content-color-done); 54 | --p-step-bullet-padding-color: var(--p-step-bullet-padding-color-done); 55 | --p-step-text-color: var(--p-step-text-color-done); 56 | &::before { line-height:0.9; text-indent:pxToRem(-1); } 57 | .icon-check { position:absolute; inset:0; } 58 | } 59 | &.is-current { 60 | --p-step-bullet-content-color: var(--p-step-bullet-content-color-current); 61 | --p-step-bullet-border-color: var(--p-step-bullet-border-color-current); 62 | --p-step-text-color: var(--p-step-text-color-current); 63 | } 64 | } 65 | 66 | &-content { line-height:1.5; } 67 | &-wrapper { 68 | position:relative; display:flex; gap:pxToRem(24); min-block-size:pxToRem(72); 69 | &::after { 70 | content:""; display:block; inline-size:pxToRem(1); 71 | position:absolute; inset-block-start:35px; inset-block-end:8px; inset-inline-start:pxToRem(11.5); 72 | background-color:hsl(var(--p-step-bullet-sep-color)); 73 | } 74 | } 75 | &:last-child { 76 | min-block-size: 0; 77 | .steps-item-wrapper::after {display:none;} 78 | } 79 | 80 | &.is-disabled { opacity:0.38; } 81 | } 82 | 83 | &-sub { 84 | display:grid; gap:pxToRem(16); padding-block:pxToRem(16); 85 | font-size:var(--font-size-0); 86 | &-item { 87 | color:hsl(var(--p-substep-text-color)); 88 | &.is-done { --p-substep-text-color:var(--p-substep-text-color-done); } 89 | &.is-current { --p-substep-text-color:var(--p-substep-text-color-current); } 90 | } 91 | } 92 | 93 | #{$theme-dark} &{ 94 | --p-step-bullet-content-color: var(--color-neutral-100); 95 | --p-step-bullet-padding-color: var(--color-neutral-100); 96 | --p-step-bullet-border-color: var(--color-neutral-60); 97 | 98 | --p-step-bullet-sep-color: var(--color-neutral-60); 99 | 100 | --p-step-bullet-content-color-done: var(--color-neutral-50); 101 | --p-step-bullet-padding-color-done: var(--color-neutral-50); 102 | 103 | /* Color Text */ 104 | --p-step-text-color: var(--color-neutral-15); 105 | --p-step-text-color-done: var(--color-neutral-50); 106 | --p-step-text-color-current: var(--color-primary-100); 107 | 108 | --p-substep-text-color: var(--color-neutral-60); 109 | --p-substep-text-color-done: var(--color-neutral-60); 110 | --p-substep-text-color-current: var(--color-neutral-20); 111 | } 112 | } -------------------------------------------------------------------------------- /src/styles/1-css-variables/_colors.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | :root { 3 | /** Primary **/ 4 | --color-primary-hue: 343; 5 | --color-primary-100: var(--color-primary-hue) 87% 56%; /* #f02e65 */ 6 | --color-primary-200: calc(var(--color-primary-hue) - 3) 79% 48%; /* #DA1A5B */ 7 | --color-primary-300: calc(var(--color-primary-hue) - 6) 87% 40%; /* #c00D53 */ 8 | 9 | /** Neutral **/ 10 | 11 | --color-neutral-0: 0 0% 100%; /* #ffffff */ 12 | --color-neutral-5: 240 11% 98%; /* #FAFAFB */ 13 | --color-neutral-10: 240 9% 94%; /* #EDEDF0 */ 14 | --color-neutral-15: 240 4% 85%; /* #D8D8DB */ 15 | --color-neutral-20: 240 3% 77%; /* #C3C3C6 */ 16 | 17 | --color-neutral-50: 240 2% 52%; /* #818186 */ 18 | --color-neutral-60: 240 2% 43%; /* #6C6C71 */ 19 | --color-neutral-70: 240 3% 35%; /* #56565C */ 20 | 21 | --color-neutral-80: 240 4% 27%; /* #414146 */ 22 | --color-neutral-85: 240 4% 18%; /* #2D2D31 */ 23 | --color-neutral-90: 240 7% 12%; /* #1D1D21 */ 24 | --color-neutral-100: 240 6% 10%; /* #19191C */ 25 | --color-neutral-105: 240 5% 8%; /* #141416 */ 26 | --color-neutral-1000:0 0% 0%; /* #000000 */ 27 | 28 | /** Information **/ 29 | --color-information-hue: 189; 30 | --color-information-10: calc(var(--color-information-hue) + 4) 88% 94%; /* #E1F7FD */ 31 | --color-information-50: calc(var(--color-information-hue) + 13) 90% 89%; /* #C8F2FC */ 32 | --color-information-100: var(--color-information-hue) 100% 38%; /* #00A7C3 */ 33 | --color-information-120: calc(var(--color-information-hue) + 1) 100% 26%; /* #007187 */ 34 | --color-information-200: calc(var(--color-information-hue) - 1) 87% 12%; /* #04333A */ 35 | 36 | /** Success **/ 37 | --color-success-hue: 150; 38 | --color-success-10: var(--color-success-hue) 88% 93%; /* #DFFDEE */ 39 | --color-success-50: var(--color-success-hue) 91% 87%; /* #BFFCDD */ 40 | --color-success-100: var(--color-success-hue) 100% 37%; /* #00BC5D */ 41 | --color-success-120: calc(var(--color-success-hue) + 8) 100% 23%; /* #00754A */ 42 | --color-success-200: calc(var(--color-success-hue) - 1) 79% 11%; /* #06331C */ 43 | 44 | /** Warning **/ 45 | --color-warning-hue: 33; 46 | --color-warning-10: calc(var(--color-warning-hue) + 1) 100% 94%; /* #FFF1DF */ 47 | --color-warning-50: calc(var(--color-warning-hue) - 2) 100% 88%; /* #FFE1C0 */ 48 | --color-warning-100: var(--color-warning-hue) 100% 48%; /* #F38500 */ 49 | --color-warning-120: calc(var(--color-warning-hue) - 9) 100% 35%; /* #B34700 */ 50 | --color-warning-200: var(--color-warning-hue) 97% 14%; /* #462701 */ 51 | 52 | /** Danger **/ 53 | --color-danger-hue: 3; 54 | --color-danger-10: calc(var(--color-danger-hue) - 3) 100% 96%; /* #FFEBEB */ 55 | --color-danger-50: calc(var(--color-danger-hue) - 2) 100% 92%; /* #FFD5D4 */ 56 | --color-danger-100: var(--color-danger-hue) 100% 61%; /* #FF453A */ 57 | --color-danger-120: calc(var(--color-danger-hue) - 3) 82% 39%; /* #B31212 */ 58 | --color-danger-200: calc(var(--color-danger-hue) - 1) 91% 13%; /* #3E0503 */ 59 | 60 | /** Blue **/ 61 | --color-blue-hue: 218; 62 | --color-blue-100: var(--color-blue-hue) 100% 82%; /* #A1C4FF */ 63 | 64 | /** Green **/ 65 | --color-green-hue: 172; 66 | --color-green-100: var(--color-green-hue) 50% 72%; /* #94DBD1 */ 67 | 68 | /** Orange **/ 69 | --color-orange-hue: 32; 70 | --color-orange-100: var(--color-orange-hue) 97% 75%; /* #FDC584 */ 71 | 72 | /** Red **/ 73 | --color-red-hue: 0; 74 | --color-red-100: var(--color-red-hue) 100% 82%; /* #FFA1A1 */ 75 | 76 | /** Purple **/ 77 | --color-purple-hue: 261; 78 | --color-purple-100: var(--color-purple-hue) 93% 84%; /* #CBB1FC */ 79 | 80 | /** Pink **/ 81 | --color-pink-hue: 331; 82 | --color-pink-100: var(--color-pink-hue) 100% 82%; /* #FFA1CE */ 83 | 84 | /* [Newly added] mint */ 85 | --color-mint-hue: 177; 86 | --color-mint-500: calc(var(--color-mint-hue) + 1) 54% 69%; 87 | /* [Finish added] */ 88 | 89 | 90 | /* transparent */ 91 | --transparent: 0 0% 0% / 0; 92 | } 93 | 94 | 95 | :root { 96 | --color-pink-text: var(--color-primary-100); 97 | 98 | --color-text-disabled: var(--color-neutral-20); 99 | --color-text-offline: var(--color-neutral-50); 100 | --color-text-info: var(--color-information-100); 101 | --color-text-danger: var(--color-danger-100); 102 | --color-text-warning: var(--color-warning-100); 103 | --color-text-success: var(--color-success-100); 104 | 105 | --color-text-gray: var(--color-neutral-50); 106 | 107 | --color-border: var(--color-neutral-10); 108 | --scroll-color: var(--color-neutral-20); 109 | 110 | #{$theme-dark} { 111 | --color-pink-text: var(--color-primary-200); 112 | 113 | --color-text-disabled: var(--color-neutral-60); 114 | --color-text-offline: var(--color-neutral-50); 115 | --color-text-info: var(--color-information-100); 116 | --color-text-danger: var(--color-danger-100); 117 | --color-text-warning: var(--color-warning-100); 118 | --color-text-success: var(--color-success-100); 119 | 120 | --color-text-gray: var(--color-neutral-20); 121 | 122 | --color-border: var(--color-neutral-85); 123 | --scroll-color: var(--color-neutral-80); 124 | } 125 | } -------------------------------------------------------------------------------- /src/styles/theme.scss: -------------------------------------------------------------------------------- 1 | @use './abstract' as *; 2 | 3 | :root { 4 | /** Primary **/ 5 | --color-primary-hue: 343; 6 | --color-primary-100: var(--color-primary-hue) 87% 56%; 7 | /* #f02e65 */ 8 | --color-primary-200: calc(var(--color-primary-hue) - 3) 79% 48%; 9 | /* #DA1A5B */ 10 | --color-primary-300: calc(var(--color-primary-hue) - 6) 87% 40%; 11 | /* #c00D53 */ 12 | 13 | /** Neutral **/ 14 | 15 | --color-neutral-0: 0 0% 100%; 16 | /* #ffffff */ 17 | --color-neutral-5: 240 11% 98%; 18 | /* #FAFAFB */ 19 | --color-neutral-10: 240 9% 94%; 20 | /* #EDEDF0 */ 21 | --color-neutral-15: 240 4% 85%; 22 | /* #D8D8DB */ 23 | --color-neutral-20: 240 3% 77%; 24 | /* #C3C3C6 */ 25 | 26 | --color-neutral-50: 240 2% 52%; 27 | /* #818186 */ 28 | --color-neutral-60: 240 2% 43%; 29 | /* #6C6C71 */ 30 | --color-neutral-70: 240 3% 35%; 31 | /* #56565C */ 32 | 33 | --color-neutral-80: 240 4% 27%; 34 | /* #414146 */ 35 | --color-neutral-85: 240 4% 18%; 36 | /* #2D2D31 */ 37 | --color-neutral-90: 240 7% 12%; 38 | /* #1D1D21 */ 39 | --color-neutral-100: 240 6% 10%; 40 | /* #19191C */ 41 | --color-neutral-105: 240 5% 8%; 42 | /* #141416 */ 43 | --color-neutral-1000: 0 0% 0%; 44 | /* #000000 */ 45 | 46 | /** Information **/ 47 | --color-information-hue: 189; 48 | --color-information-10: calc(var(--color-information-hue) + 4) 88% 94%; 49 | /* #E1F7FD */ 50 | --color-information-50: calc(var(--color-information-hue) + 13) 90% 89%; 51 | /* #C8F2FC */ 52 | --color-information-100: var(--color-information-hue) 100% 38%; 53 | /* #00A7C3 */ 54 | --color-information-120: calc(var(--color-information-hue) + 1) 100% 26%; 55 | /* #007187 */ 56 | --color-information-200: calc(var(--color-information-hue) - 1) 87% 12%; 57 | /* #04333A */ 58 | 59 | /** Success **/ 60 | --color-success-hue: 150; 61 | --color-success-10: var(--color-success-hue) 88% 93%; 62 | /* #DFFDEE */ 63 | --color-success-50: var(--color-success-hue) 91% 87%; 64 | /* #BFFCDD */ 65 | --color-success-100: var(--color-success-hue) 100% 37%; 66 | /* #00BC5D */ 67 | --color-success-120: calc(var(--color-success-hue) + 8) 100% 23%; 68 | /* #00754A */ 69 | --color-success-200: calc(var(--color-success-hue) - 1) 79% 11%; 70 | /* #06331C */ 71 | 72 | /** Warning **/ 73 | --color-warning-hue: 33; 74 | --color-warning-10: calc(var(--color-warning-hue) + 1) 100% 94%; 75 | /* #FFF1DF */ 76 | --color-warning-50: calc(var(--color-warning-hue) - 2) 100% 88%; 77 | /* #FFE1C0 */ 78 | --color-warning-100: var(--color-warning-hue) 100% 48%; 79 | /* #F38500 */ 80 | --color-warning-120: calc(var(--color-warning-hue) - 9) 100% 35%; 81 | /* #B34700 */ 82 | --color-warning-200: var(--color-warning-hue) 97% 14%; 83 | /* #462701 */ 84 | 85 | /** Danger **/ 86 | --color-danger-hue: 3; 87 | --color-danger-10: calc(var(--color-danger-hue) - 3) 100% 96%; 88 | /* #FFEBEB */ 89 | --color-danger-50: calc(var(--color-danger-hue) - 2) 100% 92%; 90 | /* #FFD5D4 */ 91 | --color-danger-100: var(--color-danger-hue) 100% 61%; 92 | /* #FF453A */ 93 | --color-danger-120: calc(var(--color-danger-hue) - 3) 82% 39%; 94 | /* #B31212 */ 95 | --color-danger-200: calc(var(--color-danger-hue) - 1) 91% 13%; 96 | /* #3E0503 */ 97 | 98 | /** Blue **/ 99 | --color-blue-hue: 218; 100 | --color-blue-100: var(--color-blue-hue) 100% 82%; 101 | /* #A1C4FF */ 102 | 103 | /** Green **/ 104 | --color-green-hue: 172; 105 | --color-green-100: var(--color-green-hue) 50% 72%; 106 | /* #94DBD1 */ 107 | 108 | /** Orange **/ 109 | --color-orange-hue: 32; 110 | --color-orange-100: var(--color-orange-hue) 97% 75%; 111 | /* #FDC584 */ 112 | 113 | /** Red **/ 114 | --color-red-hue: 0; 115 | --color-red-100: var(--color-red-hue) 100% 82%; 116 | /* #FFA1A1 */ 117 | 118 | /** Purple **/ 119 | --color-purple-hue: 261; 120 | --color-purple-100: var(--color-purple-hue) 93% 84%; 121 | /* #CBB1FC */ 122 | 123 | /** Pink **/ 124 | --color-pink-hue: 331; 125 | --color-pink-100: var(--color-pink-hue) 100% 82%; 126 | /* #FFA1CE */ 127 | 128 | /* [Newly added] mint */ 129 | --color-mint-hue: 177; 130 | --color-mint-500: calc(var(--color-mint-hue) + 1) 54% 69%; 131 | /* [Finish added] */ 132 | 133 | 134 | /* transparent */ 135 | --transparent: 0 0% 0% / 0; 136 | } 137 | 138 | 139 | :root { 140 | --color-pink-text: var(--color-primary-100); 141 | 142 | --color-text-disabled: var(--color-neutral-20); 143 | --color-text-offline: var(--color-neutral-50); 144 | --color-text-info: var(--color-information-100); 145 | --color-text-danger: var(--color-danger-100); 146 | --color-text-warning: var(--color-warning-100); 147 | --color-text-success: var(--color-success-100); 148 | 149 | --color-text-gray: var(--color-neutral-50); 150 | 151 | --color-border: var(--color-neutral-10); 152 | --scroll-color: var(--color-neutral-20); 153 | 154 | #{$theme-dark} { 155 | --color-pink-text: var(--color-primary-200); 156 | 157 | --color-text-disabled: var(--color-neutral-60); 158 | --color-text-offline: var(--color-neutral-50); 159 | --color-text-info: var(--color-information-100); 160 | --color-text-danger: var(--color-danger-100); 161 | --color-text-warning: var(--color-warning-100); 162 | --color-text-success: var(--color-success-100); 163 | 164 | --color-text-gray: var(--color-neutral-20); 165 | 166 | --color-border: var(--color-neutral-85); 167 | --scroll-color: var(--color-neutral-80); 168 | } 169 | } -------------------------------------------------------------------------------- /src/styles/6-elements/_table.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .table { 3 | /* global variable */ 4 | --heading-text-color: var(--color-neutral-60); 5 | 6 | /* local variable */ 7 | --p-table-bg-color: var(--color-neutral-0); 8 | --p-table-bg-color-focus: var(--color-neutral-5); 9 | //--p-table-bg-even-row-color: var(--color-neutral-0); 10 | --p-table-border-color: var(--color-neutral-10); 11 | --p-tbody-color-text: var(--color-neutral-60); 12 | 13 | --p-border-radius: var(--border-radius-medium); 14 | 15 | display: table; 16 | table-layout: fixed; 17 | border-collapse: collapse; 18 | background-color: hsl(var(--p-table-bg-color)); 19 | border-radius: var(--p-border-radius); 20 | box-shadow: 0 0 0 pxToRem(1) hsl(var(--color-border)), var(--shadow-small); 21 | inline-size: 100%; 22 | line-height: 1.2; 23 | 24 | &-with-scroll { 25 | @include tableScroll; overflow:hidden; 26 | border-radius:var(--border-radius-medium); 27 | 28 | .table { 29 | border-end-start-radius:0; border-end-end-radius:0; 30 | &-row { 31 | &:where(:last-child) .table-col{ border-radius:unset;} 32 | } 33 | } 34 | } 35 | &-wrapper { overflow:auto; } 36 | :where(.table-thead-col, .table-col) { 37 | display:table-cell; box-sizing:content-box; 38 | padding-block:pxToRem(24); padding-inline:pxToRem(16); vertical-align:middle; 39 | @media #{$break1} { padding-inline:pxToRem(12); } 40 | //> * {vertical-align:middle;} //make issue when there is text unwrap with wrap 41 | &:not(:first-child) { @include trim(); display:table-cell; } 42 | :where(.image) { 43 | $size: pxToRem(30); 44 | --size: #{$size}; 45 | flex-shrink: 0; 46 | img { vertical-align:bottom; } 47 | } 48 | } 49 | :where(.table-thead-col) { 50 | padding-block:pxToRem(16); 51 | } 52 | :where(.table-col) { 53 | /* for
    list tables */ 54 | --p-col-width: auto; 55 | inline-size: calc(var(--p-col-width) / 16 * 1rem); 56 | /** **/ 57 | padding-block:pxToRem(16); block-size:pxToRem(40); 58 | } 59 | &-thead { 60 | display: table-header-group; 61 | border-block-end: solid pxToRem(1) hsl(var(--p-table-border-color)); 62 | .table-row { min-block-size:pxToRem(54); } 63 | &-col { 64 | --p-col-width: auto; 65 | inline-size: calc(var(--p-col-width) / 16 * 1rem); 66 | min-inline-size: calc(var(--p-col-width) / 16 * 1rem); 67 | text-align: unset; 68 | } 69 | } 70 | &-tbody { 71 | display: table-row-group; 72 | color: hsl(var(--p-tbody-color-text)); 73 | } 74 | &-tfoot { 75 | display: table-footer-group; 76 | } 77 | &-row { 78 | display: table-row; 79 | min-block-size: pxToRem(88); 80 | &:where(a, [role*="button"]) { 81 | cursor:pointer; 82 | &:where(:hover, :focus) { 83 | background-color:hsl(var(--p-table-bg-color-focus)); 84 | :is(.table-col):first-child { background-color:hsl(var(--p-table-bg-color-focus))!important; } 85 | } 86 | } 87 | &:where(:not(:first-child)) { border-block-start:solid pxToRem(1) hsl(var(--p-table-border-color));} 88 | &:where(:last-child) { 89 | :where(.table-col:first-child) { border-end-start-radius:var(--p-border-radius); } 90 | :where(.table-col:last-child) { border-end-end-radius:var(--p-border-radius); } 91 | } 92 | } 93 | .button.is-text { 94 | --p-text-color-default: var(--color-neutral-20); 95 | } 96 | 97 | &.is-table-layout-auto { table-layout:auto; } 98 | &.is-remove-outer-styles { 99 | border-width:0; box-shadow:none; outline:none; border-radius:initial; background-color:transparent; 100 | :where(.table-thead-col) { 101 | padding-inline:0; 102 | &:where(:not(:last-child)) { padding-inline-end:pxToRem(8); } 103 | } 104 | :where(.table-col) { 105 | padding-inline:0; padding-block:pxToRem(4); 106 | &:where(:not(:last-child)) { padding-inline-end:pxToRem(8); } 107 | } 108 | :where(.table-row:last-child) { border-block-end:solid pxToRem(1) hsl(var(--p-table-border-color)); } 109 | } 110 | &.is-sticky-scroll { 111 | table-layout: revert; 112 | @media #{$break3open} { 113 | :where(.table-thead-col, .table-col):first-child { 114 | position: sticky; 115 | inset-inline-start: 0; 116 | background-color: hsl(var(--p-table-bg-color)); 117 | box-shadow: var(--shadow-large); 118 | > .text { @include trim; box-sizing:border-box; max-inline-size:pxToRem(150); } 119 | } 120 | :where(.table-thead-col, .table-col):first-child { 121 | z-index: 2; 122 | &::before { 123 | content: ""; 124 | position:absolute; inset-block:0; inset-inline-start:100%; 125 | display:block; inline-size:pxToRem(20); 126 | background: linear-gradient(to right, rgb(0 0 0 / 0.05), rgb(0 0 0 / 0) ); 127 | } 128 | } 129 | } 130 | } 131 | &.is-table-row-medium-size { 132 | :where(.table-col) { 133 | padding-block:pxToRem(8); 134 | } 135 | } 136 | 137 | #{$theme-dark} & { 138 | /* global variable */ 139 | --heading-text-color: var(--color-neutral-20); 140 | 141 | /* local variable */ 142 | --p-table-bg-color: var(--color-neutral-90); 143 | --p-table-bg-color-focus: var(--color-neutral-100); 144 | --p-table-border-color: var(--color-neutral-85); 145 | --p-tbody-color-text: var(--color-neutral-15); 146 | 147 | } 148 | @media #{$break1}, #{$break2} { 149 | &.is-vertical{ 150 | display: block; 151 | .table { 152 | &-thead { display:none; } 153 | &-tbody { display:block; } 154 | &-row { display: flex; flex-direction:column; } 155 | &-col { 156 | &:where([data-title])::before { 157 | content: attr(data-title) ": "; 158 | font-size: pxToRem(16); 159 | font-weight: 400; 160 | } 161 | } 162 | } 163 | } 164 | } 165 | @media #{$break3open} { } 166 | } -------------------------------------------------------------------------------- /src/styles/7-components/_modal.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .modal { 3 | --p-modal-title-color: var(--color-neutral-80); 4 | --p-modal-text-color: var(--color-neutral-60); 5 | --p-modal-bg-color: var(--color-neutral-0); 6 | --p-modal-border-color: var(--color-neutral-10); 7 | 8 | --p-modal-border-radius: var(--border-radius-medium); 9 | 10 | --p-modal-content-bg-color: var(--color-neutral-5); 11 | 12 | $modal-padding: pxToRem(32); 13 | --p-modal-padding: #{$modal-padding}; 14 | 15 | $header-padding-bottom: pxToRem(16); 16 | --padding-header-bottom: #{$header-padding-bottom}; 17 | 18 | display:flex; flex-direction:column; 19 | box-sizing:border-box; padding:0; 20 | 21 | inline-size: fit-content; 22 | min-inline-size: min(pxToRem(410), 95%); 23 | max-inline-size: min(pxToRem(640), 95%); 24 | max-block-size: 90vh; 25 | 26 | box-shadow: var(--shadow-large); 27 | background-color: hsl(var(--p-modal-bg-color)); 28 | border-radius: var(--p-modal-border-radius); 29 | border: solid pxToRem(1) hsl(var(--p-modal-border-color)); 30 | color: hsl(var(--p-modal-text-color)); 31 | 32 | &:where([open]) { display:flex; } 33 | &-form { min-block-size:0; display:flex; flex-direction:column; inline-size:100%; padding:var(--p-modal-padding); } 34 | &.is-small { @media #{$break2open} { inline-size:pxToRem(410); } } 35 | &.is-big { @media #{$break3open} { inline-size:pxToRem(640); } } 36 | &.is-huge { @media #{$break2open} { inline-size:pxToRem(1200); max-inline-size:90vw; } } 37 | &.is-secondary { 38 | $modal-padding: pxToRem(24); 39 | --p-modal-padding: #{$modal-padding}; 40 | 41 | $header-padding-bottom: pxToRem(16); 42 | --padding-header-bottom: #{$header-padding-bottom}; 43 | } 44 | &.is-inner-modal { 45 | --p-modal-title-color: var(--color-neutral-105); 46 | --p-modal-text-color: var(--color-neutral-60); 47 | --p-modal-bg-color: var(--color-neutral-5); 48 | --p-modal-border-color: var(--color-neutral-10); 49 | 50 | $modal-padding: pxToRem(24); 51 | --p-modal-padding: #{$modal-padding}; 52 | 53 | --p-modal-border-radius:var(--border-radius-small); 54 | 55 | max-inline-size:none; box-shadow:none; 56 | 57 | .modal-header { margin-block-end:0; } 58 | .modal-content { 59 | padding-block-start: var(--p-modal-padding); 60 | margin-block-start: var(--p-modal-padding); 61 | 62 | margin-inline: calc(var(--p-modal-padding) * -1); 63 | padding-inline: calc(var(--p-modal-padding)); 64 | border-block-start:solid pxToRem(1) hsl(var(--p-modal-border-color)); 65 | } 66 | #{$theme-dark} & { 67 | --p-modal-bg-color: var(--color-neutral-85); 68 | --p-modal-border-color: var(--color-neutral-80); 69 | } 70 | } 71 | &.is-separate-header { 72 | > .modal-form { 73 | > .modal-header { 74 | padding: var(--p-modal-padding); padding-block-start: 0; 75 | border-block-end: solid pxToRem(1) hsl(var(--color-border)); 76 | margin-inline: calc(var(--p-modal-padding) * -1); margin-block-end:0; 77 | } 78 | > .modal-content { padding-block:var(--p-modal-padding); margin-block:0; } 79 | > .modal-footer { margin-block-start:0; } 80 | } 81 | } 82 | &.is-page-in-mobile { 83 | @media #{$break1} { 84 | all:unset; block-size:unset!important; inline-size:100%; 85 | .modal { 86 | &-form { min-block-size:100dvh; padding:0; } 87 | &-header, 88 | &-footer { position:relative; z-index:1; background-color:hsl(var(--p-modal-bg-color)); padding-inline:pxToRem(16)!important; margin-inline:0!important; } 89 | &-header { position:sticky; inset-block-start:0; padding-block-start:pxToRem(16)!important; } 90 | &-footer { position:sticky; inset-block-end:0; padding-block-end:pxToRem(16); } 91 | } 92 | &::backdrop { background-color:transparent; } 93 | } 94 | } 95 | 96 | &-header { 97 | display:flex; flex-direction:column; gap:pxToRem(4); 98 | flex-shrink:0; margin-block-end:var(--padding-header-bottom); 99 | p { font-size:var(--font-size-1); } 100 | } 101 | &-title { color:hsl(var(--p-modal-title-color)); line-height:1; } 102 | &-content { 103 | @include scroll; overflow:auto; min-block-size:0; 104 | padding-block:pxToRem(4); margin-block:pxToRem(-4); /* used to show focus outline */ 105 | margin-inline: calc(var(--p-modal-padding) * -1); padding-inline: calc(var(--p-modal-padding)); 106 | &-main { background-color:hsl(var(--p-modal-content-bg-color)); } 107 | &-spacer { 108 | display:grid; gap:pxToRem(24); 109 | } 110 | } 111 | &-footer { 112 | display:grid; gap:pxToRem(16); 113 | flex-shrink:0; padding:var(--p-modal-padding); padding-block-end:pxToRem(0); 114 | margin-inline:calc(var(--p-modal-padding) * -1); margin-block-start:var(--p-modal-padding); 115 | border-block-start:solid pxToRem(1) hsl(var(--color-border)); 116 | } 117 | 118 | &::backdrop { 119 | background-color:hsl(240 5% 8% / 0.3); 120 | backdrop-filter: blur(#{pxToRem(3)}); 121 | } 122 | 123 | @media #{$break1} { 124 | $modal-padding: pxToRem(16); 125 | --p-modal-padding: #{$modal-padding}; 126 | 127 | $header-padding-bottom: pxToRem(12); 128 | --padding-header-bottom: #{$header-padding-bottom}; 129 | } 130 | 131 | #{$theme-dark} & { 132 | --p-modal-title-color: var(--color-neutral-10); 133 | --p-modal-text-color: var(--color-neutral-20); 134 | --p-modal-bg-color: var(--color-neutral-90); 135 | --p-modal-border-color: var(--color-neutral-85); 136 | 137 | --p-modal-content-bg-color: var(--color-neutral-90); 138 | 139 | --color-border: var(--color-neutral-80); 140 | 141 | &::backdrop { background-color:hsl(240 5% 8% / 0.6); } 142 | 143 | &-curtain { --p-modal-curtain-opacity: 0.6; } 144 | } 145 | } 146 | 147 | 148 | .modal-open-full-screen-mobile { 149 | @media #{$break1} { 150 | main, 151 | .wizard, 152 | .grid-with-side { display:none!important; } 153 | } 154 | } -------------------------------------------------------------------------------- /src/styles/7-components/_drop.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .drop { 3 | --p-drop-bg-color: var(--color-neutral-0); 4 | --p-drop-border-color: var(--drop-border-color, var(--color-neutral-10)); 5 | 6 | --p-drop-width-size-desltop: var(--drop-width-size-desktop); 7 | 8 | --p-drop-border-radius: var(--drop-border-radius, var(--border-radius-small)); 9 | 10 | position:absolute; inset-inline-start:0; inset-block-end:calc(100% + #{pxToRem(10)}); 11 | background-color:hsl(var(--p-drop-bg-color)); color:hsl(var(--p-drop-text-color)); padding:0; 12 | border:solid pxToRem(1) hsl(var(--p-drop-border-color)); border-radius:var(--p-drop-border-radius); box-shadow:var(--shadow-small); 13 | min-inline-size: pxToRem(208); 14 | max-inline-size: pxToRem(280); 15 | 16 | 17 | @media #{$break3open} { 18 | inline-size: var(--p-drop-width-size-desltop); 19 | max-inline-size: none; 20 | } 21 | 22 | &-header-mobile { 23 | position:sticky; top:0; z-index:10; 24 | display:flex; align-items:center; 25 | padding-block:pxToRem(16); padding-inline:pxToRem(16); border-block-end:solid pxToRem(1) hsl(var(--color-border)); 26 | background-color:hsl(var(--p-drop-bg-color)); 27 | 28 | @media #{$break3open} { 29 | display:none; 30 | } 31 | } 32 | &-footer { 33 | @media #{$break1} { 34 | position:sticky; inset-block-end:0; background-color:hsl(var(--p-drop-bg-color)); 35 | } 36 | } 37 | 38 | &::before { 39 | content: ""; position:absolute; z-index:3; inset-inline-start:pxToRem(30); inset-block-end:pxToRem(-8); 40 | inline-size:pxToRem(8); block-size:pxToRem(8); clip-path:polygon(0% 0%, 100% 0%, 50% 100%); 41 | background-color:hsl(var(--p-drop-bg-color)); 42 | } 43 | &::after { 44 | content: ""; position:absolute; z-index:2; 45 | inset-inline-start:pxToRem(29.5); inset-block-end:pxToRem(-8); transform:translateY(pxToRem(2)); 46 | inline-size:pxToRem(9); block-size:pxToRem(9); clip-path:polygon(0% 0%, 100% 0%, 50% 100%); 47 | background-color:hsl(var(--p-drop-border-color)); 48 | } 49 | &-wrapper { 50 | position:relative; inline-size:fit-content; 51 | &.is-open { z-index:1; } 52 | } 53 | &-section { 54 | $padding-horizontal: pxToRem(12); 55 | $padding-vertical: pxToRem(16); 56 | 57 | --p-section-padding-horizontal: var(--section-padding-horizontal, #{$padding-horizontal}); 58 | --p-section-padding-vertical: var(--section-padding-vertical, #{$padding-vertical}); 59 | 60 | --p-section-border-color: var(--color-neutral-10); 61 | 62 | padding-inline:var(--p-section-padding-horizontal); 63 | padding-block:var(--p-section-padding-vertical); 64 | 65 | @include scroll(); 66 | max-inline-size:pxToRem(520); margin-inline:auto; 67 | 68 | &:where(:nth-child(n +2)) { 69 | border-block-start:solid pxToRem(1) hsl(var(--p-section-border-color)); 70 | } 71 | #{$theme-dark} & { 72 | --p-section-border-color: var(--color-neutral-85); 73 | } 74 | } 75 | /** states **/ 76 | /* align states */ 77 | &:where(.is-inline-end) { inset-inline-end:pxToRem(-10); inset-inline-start:auto; } 78 | &:where(.is-block-end) { 79 | inset-block-start:calc(100% + #{pxToRem(10)}); inset-block-end:auto; 80 | &::before, &::after { inset-block-start:pxToRem(-8); inset-block-end:auto; clip-path:polygon(50% 0%, 100% 100%, 0% 100%); } 81 | &::after { transform:translateY(pxToRem(-2)); } 82 | } 83 | /* arrow align */ 84 | &.is-arrow-end { 85 | &::before, &::after { 86 | inset-inline-end:pxToRem(30); inset-inline-start:auto; 87 | } 88 | &::after { inset-inline-end:pxToRem(29.5); } 89 | } 90 | &.is-arrow-center { 91 | &::before, &::after { 92 | inset-inline-start:50%; transform:translateX(-50%); 93 | } 94 | &::after { transform:translateX(-50%) translateY(pxToRem(2)); } 95 | } 96 | &.is-no-arrow { 97 | &::before, &::after { 98 | display:none; 99 | } 100 | } 101 | &.is-full-screen-mobile { 102 | @media #{$break1}, #{$break2} { 103 | max-inline-size: none; 104 | inset: 0; 105 | } 106 | } 107 | &.is-modal-screen-mobile { 108 | @media #{$break1} { 109 | position:fixed; inset-block:0; inset-inline:pxToRem(8); 110 | padding:0; inline-size:auto; max-inline-size:none; 111 | &::backdrop { background-color:hsl(240 22% 10% / 0.6); } 112 | } 113 | 114 | } 115 | 116 | &-list { 117 | display:flex; flex-direction:column; gap:pxToRem(8); 118 | font-size: var(--font-size-0); 119 | &-item { flex-shrink:0} 120 | } 121 | &-button { 122 | --p-drop-icon-color: var(--color-neutral-20); 123 | --p-drop-text-color: var(--color-neutral-60); 124 | --p-drop-item-bg-color-hover: var(--color-neutral-10); 125 | --p-drop-item-bg-color-selected: var(--color-neutral-10); 126 | 127 | $padding-horizontal: pxToRem(12); 128 | $padding-vertical: pxToRem(10); 129 | 130 | --p-button-padding-horizontal: var(--button-padding-horizontal, #{$padding-horizontal}); 131 | --p-button-padding-vertical: var(--button-padding-vertical, #{$padding-vertical}); 132 | 133 | 134 | display:flex; gap:pxToRem(12); inline-size:100%; 135 | padding-inline:var(--p-button-padding-horizontal); 136 | padding-block:var(--p-button-padding-vertical); 137 | background-color:hsl(var(--p-drop-bg-color)); border-radius:var(--border-radius-small); 138 | -webkit-user-select:none; user-select:none; line-height: 1.5; /* 20 / 14 font-size */ 139 | .text { color:hsl(var(--p-drop-text-color)); } 140 | [class*="icon"] { 141 | align-self:center; font-size:pxToRem(16); line-height:1; color:hsl(var(--p-drop-icon-color)); 142 | &::before { vertical-align:middle; } 143 | } 144 | &:where(:focus-visible) { } 145 | &:where(:hover, :focus) { --p-drop-bg-color:var(--p-drop-item-bg-color-hover); outline:none; } 146 | &:where(.is-selected) { --p-drop-bg-color:var(--p-drop-item-bg-color-selected); } 147 | .text + [class*="icon"] { margin-inline-start:auto; } 148 | } 149 | 150 | #{$theme-dark} &{ 151 | --p-drop-bg-color: var(--color-neutral-105); 152 | --p-drop-border-color: var(--drop-border-color, var(--color-neutral-85)); 153 | &-button { 154 | --p-drop-text-color: var(--color-neutral-15); 155 | --p-drop-item-bg-color-hover: var(--color-neutral-85); 156 | --p-drop-item-bg-color-selected: var(--color-neutral-85); 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/styles/6-elements/_tag.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | .tag { 3 | $tag-height: pxToRem(32); 4 | --p-tag-height: #{$tag-height}; 5 | 6 | $tag-content-height: pxToRem(30); 7 | --p-tag-content-height: #{$tag-content-height}; 8 | 9 | $padding-inline: pxToRem(12); 10 | --p-tag-padding-inline: #{$padding-inline}; 11 | 12 | /* Light Theme */ 13 | --p-tag-text-color: var(--tag-text-color, var(--p-tag-text-color-default)); 14 | --p-tag-bg-color: var(--tag-bg-color, var(--p-tag-bg-color-default)); 15 | --p-tag-border-color: var(--tag-border-color , var(--p-tag-border-color-default)); 16 | 17 | --p-tag-text-color-default: var(--color-neutral-70); 18 | --p-tag-bg-color-default: var(--color-neutral-10); 19 | --p-tag-border-color-default:var(--p-tag-bg-color-default); 20 | 21 | --p-tag-text-color-success: var(--color-success-120); 22 | --p-tag-bg-color-success: var(--color-success-10); 23 | --p-tag-border-color-success:var(--p-tag-bg-color-success); 24 | 25 | --p-tag-text-color-warning: var(--color-warning-120); 26 | --p-tag-bg-color-warning: var(--color-warning-10); 27 | --p-tag-border-color-warning:var(--p-tag-bg-color-warning); 28 | 29 | --p-tag-text-color-danger: var(--color-danger-120); 30 | --p-tag-bg-color-danger: var(--color-danger-10); 31 | --p-tag-border-color-danger: var(--p-tag-bg-color-danger); 32 | 33 | --p-tag-text-color-info: var(--color-information-120); 34 | --p-tag-bg-color-info: var(--color-information-10); 35 | --p-tag-border-color-info: var(--p-tag-bg-color-info); 36 | 37 | /* clickable states */ 38 | --p-tag-text-color-clickable:var(--color-neutral-60); 39 | --p-tag-bg-color-clickable: var(--color-neutral-5); 40 | --p-tag-border-color-clickable:var(--color-neutral-10); 41 | 42 | --p-tag-text-color-hover: var(--color-neutral-70); 43 | --p-tag-bg-color-hover: var(--color-neutral-10); 44 | --p-tag-border-color-hover: var(--p-tag-bg-color-hover); 45 | 46 | --p-tag-text-color-active: var(--color-neutral-70); 47 | --p-tag-bg-color-active: var(--color-neutral-15); 48 | --p-tag-border-color-active: var(--p-tag-bg-color-active); 49 | 50 | --p-tag-text-color-selected: var(--p-tag-text-color-clickable); 51 | --p-tag-bg-color-selected: var(--p-tag-bg-color-clickable); 52 | --p-tag-border-color-selected: var(--color-neutral-50); 53 | 54 | --p-tag-text-color-disabled: var(--color-neutral-20); 55 | --p-tag-bg-color-disabled: var(--color-neutral-5); 56 | --p-tag-border-color-disabled: var(--color-neutral-10); 57 | /* End Light theme variables */ 58 | 59 | color: hsl(var(--p-tag-text-color)); 60 | background-color: hsl(var(--p-tag-bg-color)); 61 | border: solid pxToRem(1) hsl(var(--p-tag-border-color)); 62 | 63 | display:inline-flex; gap:pxToRem(4); justify-self:start; padding-inline:var(--p-tag-padding-inline); 64 | block-size:var(--p-tag-height); line-height:var(--p-tag-content-height); border-radius:calc(var(--p-tag-height) / 2); 65 | font-size:var(--font-size-0); font-weight:400; white-space:nowrap; -webkit-user-select:none; user-select:none; 66 | [class*="icon"] { align-self:center; font-size: inherit; } 67 | 68 | &:where(button, a) { 69 | --p-tag-text-color: var(--p-tag-text-color-clickable); 70 | --p-tag-bg-color: var(--p-tag-bg-color-clickable); 71 | --p-tag-border-color: var(--p-tag-border-color-clickable); 72 | /* is-selected is twice, because border need to keep on hover, ans text + bg color need to be less strong then hover */ 73 | &:where(.is-selected) { --p-tag-text-color:var(--p-tag-text-color-selected); --p-tag-bg-color: var(--p-tag-bg-color-selected); } 74 | &:where(:hover) { --p-tag-text-color:var(--p-tag-text-color-hover); --p-tag-bg-color:var(--p-tag-bg-color-hover); --p-tag-border-color:var(--p-tag-border-color-hover); } 75 | &:where(:active) { --p-tag-text-color:var(--p-tag-text-color-active); --p-tag-bg-color: var(--p-tag-bg-color-active); --p-tag-border-color:var(--p-tag-border-color-active); } 76 | &:where(.is-selected) { --p-tag-border-color:var(--p-tag-border-color-selected); } 77 | &:where(#{$disabled}) { --p-tag-text-color:var(--p-tag-text-color-disabled); --p-tag-bg-color:var(--p-tag-bg-color-disabled); --p-tag-border-color:var(--p-tag-border-color-disabled); } 78 | 79 | /* smartphones, touchscreens */ 80 | @media (hover: none) and (pointer: coarse) { 81 | $tag-height: pxToRem(42); 82 | --p-tag-height: #{$tag-height}; 83 | 84 | $tag-content-height: pxToRem(40); 85 | --p-tag-content-height: #{$tag-content-height}; 86 | } 87 | } 88 | 89 | &.is-success { --p-tag-text-color:var(--p-tag-text-color-success); --p-tag-bg-color:var(--p-tag-bg-color-success); --p-tag-border-color:var(--p-tag-border-color-success); } 90 | &.is-warning { --p-tag-text-color:var(--p-tag-text-color-warning); --p-tag-bg-color:var(--p-tag-bg-color-warning); --p-tag-border-color:var(--p-tag-border-color-warning); } 91 | &.is-danger { --p-tag-text-color:var(--p-tag-text-color-danger); --p-tag-bg-color:var(--p-tag-bg-color-danger); --p-tag-border-color:var(--p-tag-border-color-danger); } 92 | &.is-info { --p-tag-text-color:var(--p-tag-text-color-info); --p-tag-bg-color:var(--p-tag-bg-color-info); --p-tag-border-color:var(--p-tag-border-color-info); } 93 | 94 | /* Theme Dark */ 95 | #{$theme-dark} & { 96 | --p-tag-text-color-default: var(--color-neutral-20); 97 | --p-tag-bg-color-default: var(--color-neutral-80); 98 | 99 | --p-tag-text-color-success: var(--color-success-100); 100 | --p-tag-bg-color-success: var(--color-success-200); 101 | 102 | --p-tag-text-color-warning: var(--color-warning-100); 103 | --p-tag-bg-color-warning: var(--color-warning-200); 104 | 105 | --p-tag-text-color-danger: var(--color-danger-100); 106 | --p-tag-bg-color-danger: var(--color-danger-200); 107 | 108 | --p-tag-text-color-info: var(--color-information-100); 109 | --p-tag-bg-color-info: var(--color-information-200); 110 | 111 | /* clickable state */ 112 | --p-tag-text-color-clickable: var(--color-neutral-20); 113 | --p-tag-bg-color-clickable: var(--color-neutral-85); 114 | --p-tag-border-color-clickable: var(--color-neutral-80); 115 | 116 | --p-tag-text-color-hover: var(--color-neutral-20); 117 | --p-tag-bg-color-hover: var(--color-neutral-80); 118 | --p-tag-border-color-hover: var(--color-neutral-80); 119 | 120 | --p-tag-text-color-active: var(--color-neutral-20); 121 | --p-tag-bg-color-active: var(--color-neutral-100); 122 | --p-tag-border-color-active: var(--color-neutral-100); 123 | 124 | --p-tag-text-color-disabled: var(--color-neutral-70); 125 | --p-tag-bg-color-disabled: var(--color-neutral-85); 126 | --p-tag-border-color-disabled: var(--color-neutral-85); 127 | } 128 | } -------------------------------------------------------------------------------- /src/styles/6-elements/form/_radio-and-checkbox.scss: -------------------------------------------------------------------------------- 1 | @use '../../abstract' as *; 2 | 3 | [type="checkbox"], 4 | [type="radio"] { 5 | $size: pxToRem(20); 6 | --p-size: #{$size}; 7 | --p-icon-size: calc(var(--p-size) * 0.85); 8 | 9 | /* Theme Light */ 10 | --p-icon-color: var(--p-icon-color-default); 11 | --p-bg-color: var(--p-bg-color-default); 12 | --p-border-color: var(--p-border-color-default); 13 | 14 | --p-icon-color-default: var(--color-neutral-0); 15 | --p-bg-color-default: var(--color-neutral-0); 16 | --p-border-color-default: var(--color-neutral-20); 17 | 18 | --p-bg-color-checked: var(--color-information-100); 19 | --p-border-color-checked: var(--color-information-100); 20 | 21 | --p-bg-color-hover: var(--color-neutral-5); 22 | --p-border-color-hover:var(--color-neutral-20); 23 | 24 | --p-bg-color-hover-checked: var(--color-information-100); 25 | --p-border-color-hover-checked: var(--color-information-100); 26 | 27 | --p-bg-color-indeterminate: var(--color-information-100); 28 | --p-border-color-indeterminate: var(--color-information-100); 29 | 30 | --p-bg-color-active: var(--color-neutral-0); 31 | --p-border-color-active: var(--color-information-120); 32 | 33 | --p-bg-color-active-checked: var(--color-information-120); 34 | --p-border-color-active-checked: var(--color-information-120); 35 | 36 | --p-bg-color-disabled: var(--color-neutral-10); 37 | --p-border-color-ddisabled: var(--color-neutral-15); 38 | 39 | --p-icon-color-disabled-checked: var(--color-neutral-0); 40 | --p-bg-color-disabled-checked: var(--color-neutral-15); 41 | --p-border-color-disabled-checked: var(--color-neutral-15); 42 | /* End theme variables */ 43 | 44 | display:inline-grid; place-content:center; flex-shrink:0; 45 | inline-size:var(--p-size); block-size:var(--p-size); 46 | background:hsl(var(--p-bg-color)); border:solid pxToRem(1) hsl(var(--p-border-color)); 47 | color:hsl(var(--p-icon-color)); vertical-align:middle; cursor:pointer; 48 | 49 | &.is-small { $size:pxToRem(16); --p-size:#{$size}; } 50 | &.is-large { $size:pxToRem(24); --p-size:#{$size}; } 51 | //&:where(:disabled) { opacity:0.5; filter:grayscale(1); } 52 | 53 | &:where(:focus) { 54 | $focus: 0 0 0 pxToRem(1) hsl(var(--color-information-100)), 0 0 0 pxToRem(2) hsl(var(--color-information-100) / 0.25); 55 | --focus-box-shadow: #{$focus}; 56 | } 57 | 58 | &:where(:checked) { 59 | --p-bg-color: var(--p-bg-color-checked); 60 | --p-border-color: var(--p-border-color-checked); 61 | } 62 | 63 | &:where(:hover) { 64 | --p-bg-color: var(--p-bg-color-hover); 65 | --p-border-color: var(--p-border-color-hover); 66 | &:where(:checked) { 67 | --p-bg-color: var(--p-bg-color-hover-checked); 68 | --p-border-color: var(--p-border-color-hover-checked); 69 | } 70 | } 71 | &:where(:indeterminate) { 72 | --p-bg-color: var(--p-bg-color-indeterminate); 73 | --p-border-color: var(--p-border-color-indeterminate); 74 | } 75 | &:where(:active) { 76 | --p-bg-color: var(--p-bg-color-active); 77 | --p-border-color: var(--p-border-color-active); 78 | &:where(:checked) { 79 | --p-bg-color: var(--p-bg-color-active-checked); 80 | --p-border-color: var(--p-border-color-active-checked); 81 | } 82 | } 83 | &:where(:disabled) { 84 | --p-bg-color: var(--p-bg-color-disabled); 85 | --p-border-color: var(--p-border-color-ddisabled); 86 | cursor: initial; 87 | &:where(:checked) { 88 | --p-icon-color: var(--p-icon-color-disabled-checked); 89 | --p-bg-color: var(--p-bg-color-disabled-checked); 90 | --p-border-color: var(--p-border-color-disabled-checked); 91 | } 92 | } 93 | 94 | /* Theme Dark */ 95 | #{$theme-dark} & { 96 | --p-bg-color-disabled: var(--color-neutral-80); 97 | --p-border-color-ddisabled: var(--color-neutral-70); 98 | 99 | --p-icon-color-disabled-checked: var(--color-neutral-60); 100 | --p-bg-color-disabled-checked: var(--color-neutral-80); 101 | --p-border-color-disabled-checked: var(--color-neutral-80); 102 | } 103 | } 104 | 105 | 106 | [type="radio"] { 107 | position:relative; border-radius:var(--border-radius-circular); 108 | &:where(:checked) { 109 | padding:calc(var(--p-size) * 0.2); 110 | &::before { 111 | content:""; display:block; 112 | position:absolute; inset:30%; 113 | background-color:hsl(var(--p-icon-color)); border-radius:var(--border-radius-circular); 114 | } 115 | } 116 | } 117 | [type="checkbox"] { 118 | border-radius: var(--border-radius-xsmall); 119 | &:where(:indeterminate) { 120 | &::after { 121 | content:""; display:block; inline-size:pxToRem(10); block-size:pxToRem(2); border-radius:pxToRem(1); 122 | background-color:hsl(var(--color-neutral-0)); 123 | } 124 | 125 | } 126 | &:where(:checked) { 127 | &::before { 128 | font-family: 'icon' !important; 129 | content: var(--icon-check); 130 | vertical-align: middle; 131 | margin-bottom: calc(var(--p-size) / 8 * -1); 132 | font-size: var(--p-icon-size); 133 | } 134 | } 135 | &:where(:not(:checked)) { 136 | &::before { display:none; } 137 | } 138 | } 139 | 140 | .checkboxes { 141 | &-header { display:flex; justify-content:space-between; } 142 | &-options { display:flex; gap:pxToRem(10); font-size:pxToRem(13); } 143 | &-list { display:grid; grid-template-columns:repeat(2, 1fr); gap:pxToRem(30);} 144 | &-item { 145 | :where([type="checkbox"], [type="radio"]) { margin-inline-end:pxToRem(10); } 146 | } 147 | } 148 | 149 | .radio-button { 150 | all:unset; 151 | 152 | --p-radio-bitton-text-color: var(--p-radio-bitton-text-color-default); 153 | --p-radio-bitton-bg-color: var(--p-radio-bitton-bg-color-default); 154 | --p-radio-bitton-border-color: var(--p-radio-bitton-border-color-default); 155 | 156 | --p-radio-bitton-text-color-default: var(--color-neutral-60); 157 | --p-radio-bitton-bg-color-default: var(--color-neutral-5); 158 | --p-radio-bitton-border-color-default: var(--color-neutral-15); 159 | 160 | --p-radio-bitton-text-color-checked: var(--p-radio-bitton-text-color-default); 161 | --p-radio-bitton-bg-color-checked: var(--color-neutral-15); 162 | --p-radio-bitton-border-color-checked: var(--p-radio-bitton-border-color-default); 163 | 164 | color: hsl(var(--p-radio-bitton-text-color)); 165 | background-color: hsl(var(--p-radio-bitton-bg-color)); 166 | border: solid pxToRem(1) hsl(var(--p-radio-bitton-border-color)); 167 | 168 | display:grid; place-content:center; box-sizing:border-box; padding:0; 169 | inline-size:pxToRem(33); block-size:pxToRem(36); border-radius:var(--border-radius-small); 170 | font-weight:bold; cursor:pointer; transition:var(--transition); 171 | 172 | &::before { content: attr(data-text); } 173 | 174 | &:where(:hover) { 175 | scale:1.1; 176 | } 177 | &:where(:focus-visible) { 178 | box-shadow:var(--focus-box-shadow); scale:1.1; 179 | } 180 | &:where(:checked) { 181 | &::before { position:initial; background:initial; } /* overrides default radio */ 182 | --p-radio-bitton-text-color: var(--p-radio-bitton-text-color-checked); 183 | --p-radio-bitton-bg-color: var(--p-radio-bitton-bg-color-checked); 184 | --p-radio-bitton-border-color: var(--p-radio-bitton-border-color-checked); 185 | } 186 | 187 | #{$theme-dark} & { 188 | --p-radio-bitton-text-color-default: var(--color-neutral-20); 189 | --p-radio-bitton-bg-color-default: var(--color-neutral-85); 190 | --p-radio-bitton-border-color-default: var(--color-neutral-80); 191 | 192 | --p-radio-bitton-text-color-checked: var(--p-radio-bitton-text-color-default); 193 | --p-radio-bitton-bg-color-checked: var(--color-neutral-80); 194 | --p-radio-bitton-border-color-checked: var(--color-neutral-60); 195 | } 196 | } 197 | 198 | .image-radio { 199 | display:flex; flex-direction:column; gap:pxToRem(12); cursor:pointer; 200 | [type="radio"] { display:block; margin-inline:auto; } 201 | } 202 | 203 | .choice-item { 204 | --p-choice-item-title-color: var(--color-neutral-70); 205 | --p-choice-item-text-color: var(--color-neutral-60); 206 | display:flex; gap:pxToRem(8); 207 | &-content { display:flex; flex-direction:column; gap:pxToRem(4); line-height:1.5; } 208 | &-title { color:hsl(var(--p-choice-item-title-color)); font-weight:600;} 209 | &-paragraph { color:hsl(var(--p-choice-item-text-color)); } 210 | 211 | #{$theme-dark} & { 212 | --p-choice-item-title-color: var(--color-neutral-10); 213 | --p-choice-item-text-color: var(--color-neutral-20); 214 | } 215 | } -------------------------------------------------------------------------------- /src/styles/6-elements/_avatar.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .avatar { 4 | --p-text-size: var(--text-size, var(--font-size-0)); 5 | --p-image-size: var(--image-size, #{pxToRem(20)} ); 6 | --p-size: var(--size, #{pxToRem(40)} ); /* default is medium size */ 7 | 8 | --p-avatar-text-color: var(--p-avatar-text-color-default); 9 | --p-avatar-bg-color: var(--p-avatar-bg-color-default); 10 | --p-avatar-border-color: var(--p-avatar-border-color-default); 11 | 12 | /* default */ 13 | --p-avatar-text-color-default: var(--color-neutral-60); 14 | --p-avatar-bg-color-default: var(--color-neutral-5); 15 | --p-avatar-border-color-default: var(--color-neutral-10); 16 | 17 | /* empty */ 18 | --p-avatar-text-color-empty: var(--color-neutral-20); 19 | --p-avatar-bg-color-empty: var(--transparent); 20 | --p-avatar-border-color-empty: var(--color-neutral-20); 21 | 22 | /* orange */ 23 | --p-avatar-text-color-orange: var(--color-neutral-0); 24 | --p-avatar-bg-color-orange: var(--color-orange-100); 25 | --p-avatar-border-color-orange: var(--p-avatar-bg-color-orange); 26 | 27 | /* green */ 28 | --p-avatar-text-color-green: var(--color-neutral-0); 29 | --p-avatar-bg-color-green: var(--color-green-100); 30 | --p-avatar-border-color-green: var(--p-avatar-bg-color-green); 31 | 32 | /* blue */ 33 | --p-avatar-text-color-blue: var(--color-neutral-0); 34 | --p-avatar-bg-color-blue: var(--color-blue-100); 35 | --p-avatar-border-color-blue: var(--p-avatar-bg-color-blue); 36 | 37 | /* pink */ 38 | --p-avatar-text-color-pink: var(--color-neutral-0); 39 | --p-avatar-bg-color-pink: var(--color-pink-100); 40 | --p-avatar-border-color-pink: var(--p-avatar-bg-color-pink); 41 | 42 | /* red */ 43 | --p-avatar-text-color-red: var(--color-neutral-0); 44 | --p-avatar-bg-color-red: var(--color-red-100); 45 | --p-avatar-border-color-red: var(--p-avatar-bg-color-red); 46 | 47 | 48 | --color-text-info: var(--color-information-100); 49 | --color-text-danger: var(--color-danger-100); 50 | --color-text-warning: var(--color-warning-100); 51 | --color-text-success: var(--color-success-100); 52 | 53 | 54 | /* info */ 55 | --p-avatar-text-info: var(--color-neutral-0); 56 | --p-avatar-bg-info: var(--color-text-info); 57 | --p-avatar-border-info: var(--p-avatar-bg-info); 58 | 59 | /* danger */ 60 | --p-avatar-text-danger: var(--color-neutral-0); 61 | --p-avatar-bg-danger: var(--color-text-danger); 62 | --p-avatar-border-danger: var(--p-avatar-bg-danger); 63 | 64 | /* warning */ 65 | --p-avatar-text-warning: var(--color-neutral-0); 66 | --p-avatar-bg-warning: var(--color-text-warning); 67 | --p-avatar-border-warning: var(--p-avatar-bg-warning); 68 | 69 | /* success */ 70 | --p-avatar-text-success: var(--color-neutral-0); 71 | --p-avatar-bg-success: var(--color-text-success); 72 | --p-avatar-border-success: var(--p-avatar-bg-success); 73 | 74 | color: hsl(var(--p-avatar-text-color)); 75 | background-color: hsl(var(--p-avatar-bg-color)); 76 | border: solid pxToRem(1) hsl(var(--p-avatar-border-color)); 77 | 78 | font-size: var(--p-text-size); 79 | inline-size: var(--p-size); 80 | block-size: var(--p-size); 81 | 82 | /* fix shrinking issue */ 83 | min-inline-size: var(--p-size); 84 | min-block-size: var(--p-size); 85 | max-inline-size: var(--p-size); 86 | max-block-size: var(--p-size); 87 | 88 | border-radius: var(--border-radius-circular); 89 | 90 | display: grid; 91 | place-content: center; 92 | flex-shrink: 0; /* in case it a child of flexbox */ 93 | box-sizing: content-box; 94 | overflow: hidden; 95 | text-transform: uppercase; 96 | -webkit-user-select: none; 97 | user-select: none; 98 | line-height: 1; 99 | 100 | [class*="icon"] { font-size:var(--p-text-size)!important; } 101 | img, svg { inline-size:var(--p-image-size); block-size:var(--p-image-size); } 102 | &-link { 103 | display:block; border-radius:var(--border-radius-circular); 104 | &:focus-visible { box-shadow:var(--focus-box-shadow); } 105 | } 106 | /* sizes */ 107 | &.is-size-x-small { 108 | --p-text-size: #{pxToRem(10)}; 109 | --p-size: #{pxToRem(24)}; 110 | --p-image-size: #{pxToRem(16)}; 111 | &.is-with-3-char { --p-text-size:#{pxToRem(8)}; } 112 | [class*="icon"] { --p-text-size:var(--font-size-0); } 113 | } 114 | &.is-size-small { 115 | --p-text-size: var(--font-size-00); 116 | --p-size: #{pxToRem(32)}; 117 | --p-image-size: #{pxToRem(20)}; 118 | &.is-with-3-char { --p-text-size:#{pxToRem(10)}; } 119 | [class*="icon"] { --p-text-size:var(--font-size-0); } 120 | .icon-question-mark-circle { --p-text-size:var(--font-size-2); } 121 | } 122 | &.is-size-medium { 123 | /* default */ 124 | &.is-with-3-char { --p-text-size:var(--font-size-0); } 125 | [class*="icon"] { --p-text-size:var(--font-size-1); } 126 | } 127 | &.is-size-large { 128 | --p-text-size:var(--font-size-1); 129 | --p-size:#{pxToRem(48)}; 130 | --p-image-size: #{pxToRem(24)}; 131 | &.is-with-3-char { --p-text-size:var(--font-size-0); } 132 | [class*="icon"] { --p-text-size:var(--font-size-4); } 133 | } 134 | &.is-size-x-large { 135 | --p-text-size:var(--font-size-4); 136 | --p-size:#{pxToRem(64)}; 137 | --p-image-size: #{pxToRem(24)}; 138 | &.is-with-3-char { --p-text-size:var(--font-size-2); } 139 | [class*="icon"] { --p-text-size:var(--font-size-4); } 140 | } 141 | 142 | /* color states */ 143 | &.is-color-empty { 144 | border-style: dashed; 145 | --p-avatar-text-color: var(--p-avatar-text-color-empty); 146 | --p-avatar-bg-color: var(--p-avatar-bg-color-empty); 147 | --p-avatar-border-color: var(--p-avatar-border-color-empty); 148 | } 149 | &.is-color-orange { 150 | --p-avatar-text-color: var(--p-avatar-text-color-orange); 151 | --p-avatar-bg-color: var(--p-avatar-bg-color-orange); 152 | --p-avatar-border-color: var(--p-avatar-border-color-orange); 153 | } 154 | &.is-color-green { 155 | --p-avatar-text-color: var(--p-avatar-text-color-green); 156 | --p-avatar-bg-color: var(--p-avatar-bg-color-green); 157 | --p-avatar-border-color: var(--p-avatar-border-color-green); 158 | } 159 | &.is-color-blue { 160 | --p-avatar-text-color: var(--p-avatar-text-color-blue); 161 | --p-avatar-bg-color: var(--p-avatar-bg-color-blue); 162 | --p-avatar-border-color: var(--p-avatar-border-color-blue); 163 | } 164 | &.is-color-pink { 165 | --p-avatar-text-color: var(--p-avatar-text-color-pink); 166 | --p-avatar-bg-color: var(--p-avatar-bg-color-pink); 167 | --p-avatar-border-color: var(--p-avatar-border-color-pink); 168 | } 169 | &.is-color-red { 170 | --p-avatar-text-color: var(--p-avatar-text-color-red); 171 | --p-avatar-bg-color: var(--p-avatar-bg-color-red); 172 | --p-avatar-border-color: var(--p-avatar-border-color-red); 173 | } 174 | 175 | /* message Avatars colors */ 176 | &.is-info { 177 | --p-avatar-text-color: var(--p-avatar-text-info); 178 | --p-avatar-bg-color: var(--p-avatar-bg-info); 179 | --p-avatar-border-color: var(--p-avatar-border-info); 180 | } 181 | 182 | &.is-warning { 183 | --p-avatar-text-color: var(--p-avatar-text-warning); 184 | --p-avatar-bg-color: var(--p-avatar-bg-warning); 185 | --p-avatar-border-color: var(--p-avatar-border-warning); 186 | } 187 | 188 | &.is-danger { 189 | --p-avatar-text-color: var(--p-avatar-text-danger); 190 | --p-avatar-bg-color: var(--p-avatar-bg-danger); 191 | --p-avatar-border-color: var(--p-avatar-border-danger); 192 | } 193 | 194 | &.is-success { 195 | --p-avatar-text-color: var(--p-avatar-text-success); 196 | --p-avatar-bg-color: var(--p-avatar-bg-success); 197 | --p-avatar-border-color: var(--p-avatar-border-success); 198 | } 199 | 200 | 201 | #{$theme-dark} & { 202 | /* default */ 203 | --p-avatar-text-color-default: var(--color-neutral-20); 204 | --p-avatar-bg-color-default: var(--color-neutral-85); 205 | --p-avatar-border-color-default: var(--color-neutral-80); 206 | 207 | /* colors avatars*/ 208 | --p-avatar-text-color-orange: var(--color-neutral-80); 209 | --p-avatar-text-color-green: var(--color-neutral-80); 210 | --p-avatar-text-color-blue: var(--color-neutral-80); 211 | --p-avatar-text-color-pink: var(--color-neutral-80); 212 | --p-avatar-text-color-red: var(--color-neutral-80); 213 | 214 | 215 | } 216 | } 217 | 218 | .avatars-group { 219 | --p-avatar-group-border-color: var(--avatar-group-border-color, var(--color-neutral-10)); 220 | position:relative; z-index:0; display:flex; 221 | &-item { 222 | position: relative; 223 | display: inline-flex; 224 | @for $i from 1 through 10 { 225 | &:nth-child(#{$i}) { 226 | $zindex: 10 - $i; 227 | z-index: $zindex; 228 | } 229 | } 230 | .avatar { 231 | border:solid pxToRem(1) hsl(var(--p-avatar-group-border-color)); border-radius:var(--border-radius-circular); 232 | margin-inline-start: -.6rem; 233 | } 234 | .image-item { margin-inline-start: -.6rem; } 235 | 236 | .is-size-x-small { margin-inline-start: -.5rem; } 237 | .is-size-small { margin-inline-start: -.5rem; } 238 | .is-size-large { margin-inline-start: -0.8rem; } 239 | } 240 | #{$theme-dark} & { 241 | --p-avatar-group-border-color: var(--color-neutral-80); 242 | } 243 | } -------------------------------------------------------------------------------- /src/styles/6-elements/_button.scss: -------------------------------------------------------------------------------- 1 | @use '../abstract' as *; 2 | 3 | .button { 4 | $button-size: pxToRem(40); 5 | --p-button-size: var(--button-size, #{$button-size}); 6 | 7 | $padding-horizontal: pxToRem(16); 8 | --padding-horizontal: #{$padding-horizontal}; 9 | 10 | $font-size: pxToRem(14); 11 | --p-font-size: #{$font-size}; 12 | 13 | /* Light Theme */ 14 | --p-text-color: var(--p-text-color-default); 15 | --p-button-color: var(--p-button-color-default); 16 | --p-border-color: var(--p-border-color-default); 17 | 18 | --p-text-color-default: var(--color-neutral-5); 19 | --p-button-color-default: var(--color-primary-200); 20 | --p-border-color-default: var(--color-primary-300); 21 | 22 | --p-text-color-hover: var(--p-text-color-default); 23 | --p-button-color-hover: var(--color-primary-100); 24 | --p-border-color-hover: var(--p-border-color-default); 25 | 26 | --p-text-color-focus: var(--p-text-color-default); 27 | --p-button-color-focus: var(--color-primary-200); 28 | --p-border-color-focus: var(--color-primary-200); 29 | 30 | --p-text-color-active: var(--p-text-color-default); 31 | --p-button-color-active: var(--color-primary-300); 32 | --p-border-color-active: var(--color-primary-300); 33 | 34 | --p-text-color-disabled: var(--color-neutral-20); 35 | --p-button-color-disabled: var(--color-neutral-10); 36 | --p-border-color-disabled: var(--color-neutral-10); 37 | 38 | /* End Light theme variables */ 39 | 40 | @include trim(); 41 | display:flex; gap:pxToRem(8); align-items:center; inline-size:fit-content; block-size:var(--p-button-size); 42 | padding-inline:var(--padding-horizontal); cursor:pointer; font-size:var(--p-font-size); font-weight:600; 43 | color:hsl(var(--p-text-color)); background-color:hsl(var(--p-button-color)); text-align:center; 44 | border:solid pxToRem(1) hsl(var(--p-border-color)); border-radius:var(--border-radius-xsmall); flex-shrink:0; 45 | -webkit-user-select:none; user-select:none; 46 | 47 | [class*="icon"] { 48 | line-height: 1; 49 | &::before { vertical-align:middle; } 50 | } 51 | 52 | &.is-small { 53 | $button-size: pxToRem(32); 54 | --p-button-size: var(--button-size, #{$button-size}); 55 | } 56 | &.is-big { 57 | $font-size: pxToRem(16); 58 | --p-font-size: #{$font-size}; 59 | 60 | $button-size:pxToRem(48); --p-button-size:#{$button-size}; 61 | $padding-horizontal:pxToRem(20); --padding-horizontal: #{$padding-horizontal}; 62 | } 63 | &.is-only-icon { aspect-ratio:1 / 1; padding:0; justify-content:center; align-items:center; border-radius:var(--border-radius-circular); } 64 | &.is-full-width { inline-size:100%; justify-content:center; } 65 | &.is-full-width-mobile { @media #{$break1} {inline-size:100%; justify-content:center; } } 66 | &.is-full-width-in-stack-mobile { @media #{$break1} { flex-grow:1; justify-content:center; } } 67 | /* default - PRIMARY */ 68 | &:is(:hover) { 69 | &:where(:not(#{$disabled})) { 70 | --p-text-color: var(--p-text-color-hover); 71 | --p-button-color: var(--p-button-color-hover); 72 | --p-border-color: var(--p-border-color-hover); 73 | } 74 | } 75 | &:is(:focus-visible) { 76 | &:where(:not(#{$disabled})) { 77 | --p-text-color: var(--p-text-color-focus); 78 | --p-button-color: var(--p-button-color-focus); 79 | --p-border-color: var(--p-border-color-focus); 80 | } 81 | } 82 | &:is(:active) { 83 | &:where(:not(#{$disabled})) { 84 | --p-text-color: var(--p-text-color-active); 85 | --p-button-color: var(--p-button-color-active); 86 | --p-border-color: var(--p-border-color-active); 87 | } 88 | } 89 | &:where(#{$disabled}) { 90 | --p-text-color: var(--p-text-color-disabled); 91 | --p-button-color: var(--p-button-color-disabled); 92 | --p-border-color: var(--p-border-color-disabled); 93 | cursor: unset; 94 | /* opacity:0.3; filter:grayscale(1); - old styles */ 95 | } 96 | /** DARK MODE **/ 97 | #{$theme-dark} & { 98 | --p-button-color-default: var(--color-primary-200); 99 | --p-border-color-default: var(--color-primary-200); 100 | 101 | --p-button-color-hover: var(--color-primary-100); 102 | --p-border-color-hover: var(--color-primary-100); 103 | 104 | --p-border-color-focus: var(--color-primary-300); 105 | 106 | --p-border-color-active: var(--color-primary-300); 107 | 108 | --p-text-color-disabled: var(--color-neutral-60); 109 | --p-button-color-disabled: var(--color-neutral-80); 110 | --p-border-color-disabled: var(--color-neutral-80); 111 | } 112 | /** end main button */ 113 | 114 | /* special color */ 115 | &.is-github { 116 | --p-text-color-default: var(--color-neutral-0); 117 | --p-button-color-default: var(--color-neutral-80); 118 | --p-border-color-default: var(--color-neutral-80); 119 | 120 | --p-text-color-hover: var(--p-text-color-default); 121 | --p-button-color-hover: var(--p-button-color-default); 122 | --p-border-color-hover: var(--p-border-color-default); 123 | 124 | --p-text-color-focus: var(--p-text-color-default); 125 | --p-button-color-focus: var(--p-button-color-default); 126 | --p-border-color-focus: var(--p-border-color-default); 127 | 128 | --p-text-color-active: var(--p-text-color-default); 129 | --p-button-color-active: var(--p-button-color-default); 130 | --p-border-color-active: var(--p-border-color-default); 131 | } 132 | 133 | &.is-secondary { 134 | --p-text-color-default: var(--color-neutral-60); 135 | --p-button-color-default: var(--color-neutral-5); 136 | --p-border-color-default: var(--color-neutral-15); 137 | 138 | --p-text-color-hover: var(--p-text-color-default); 139 | --p-button-color-hover: var(--color-neutral-10); 140 | --p-border-color-hover: var(--p-border-color-default); 141 | 142 | --p-text-color-focus: var(--p-text-color-default); 143 | --p-button-color-focus: var(--p-button-color-default); 144 | --p-border-color-focus: var(--transparent); 145 | 146 | --p-text-color-active: var(--color-neutral-90); 147 | --p-button-color-active: var(--color-neutral-15); 148 | --p-border-color-active: var(--color-neutral-15); 149 | 150 | --p-text-color-disabled: var(--color-neutral-20); 151 | --p-button-color-disabled: var(--p-button-color-default); 152 | --p-border-color-disabled: var(--color-neutral-15); 153 | 154 | 155 | /** DARK MODE **/ 156 | #{$theme-dark} & { 157 | --p-text-color-default: var(--color-neutral-5); 158 | --p-button-color-default: var(--color-neutral-90); 159 | --p-border-color-default: var(--color-neutral-80); 160 | 161 | --p-text-color-hover: var(--p-text-color-default); 162 | --p-button-color-hover: var(--transparent); 163 | --p-border-color-hover: var(--color-neutral-70); 164 | 165 | --p-text-color-focus: var(--p-text-color-default); 166 | --p-button-color-focus: var(--p-button-color-default); 167 | --p-border-color-focus: var(--transparent); 168 | 169 | --p-text-color-active: var(--p-text-color-default); 170 | --p-button-color-active: var(--p-button-color-default); 171 | --p-border-color-active: var(--color-neutral-60); 172 | 173 | --p-text-color-disabled: var(--color-neutral-60); 174 | --p-button-color-disabled: var(--p-button-color-default); 175 | --p-border-color-disabled: var(--color-neutral-80); 176 | } 177 | } 178 | 179 | &.is-text { 180 | --p-text-color-default: var(--color-neutral-60); 181 | --p-button-color-default: var(--transparent); 182 | --p-border-color-default: var(--transparent); 183 | 184 | --p-text-color-hover: var(--color-neutral-70); 185 | --p-button-color-hover: var(--p-button-color-default); 186 | --p-border-color-hover: var(--p-border-color-default); 187 | 188 | --p-text-color-focus: var(--p-text-color-default); 189 | --p-button-color-focus: var(--color-neutral-5); 190 | --p-border-color-focus: var(--p-border-color-default); 191 | 192 | --p-text-color-active: var(--color-neutral-90); 193 | --p-button-color-active: var(--p-button-color-default); 194 | --p-border-color-active: var(--p-border-color-default); 195 | 196 | 197 | --p-text-color-disabled: var(--color-neutral-20); 198 | --p-button-color-disabled: var(--p-button-color-default); 199 | --p-border-color-disabled: var(--p-border-color-default); 200 | 201 | /** DARK MODE **/ 202 | #{$theme-dark} & { 203 | 204 | --p-text-color-default: var(--color-neutral-5); 205 | --p-button-color-default: var(--transparent); 206 | --p-border-color-default: var(--transparent); 207 | 208 | --p-text-color-hover: var(--color-neutral-20); 209 | --p-button-color-hover: var(--p-button-color-default); 210 | --p-border-color-hover: var(--p-border-color-default); 211 | 212 | --p-text-color-focus: var(--color-neutral-5); 213 | --p-button-color-focus: var(--p-button-color-default); 214 | --p-border-color-focus: var(--p-border-color-default); 215 | 216 | --p-text-color-active: var(--p-text-color-default); 217 | --p-button-color-active: var(--p-button-color-default); 218 | --p-border-color-active: var(--p-border-color-default); 219 | 220 | --p-text-color-disabled: var(--color-neutral-60); 221 | --p-button-color-disabled: var(--p-button-color-default); 222 | --p-border-color-disabled: var(--p-border-color-default); 223 | } 224 | } 225 | } --------------------------------------------------------------------------------