diff --git a/js/react/lib/components/avatar/avatar.component.tsx b/js/react/lib/components/avatar/avatar.component.tsx index 897a859..ab2f2c4 100644 --- a/js/react/lib/components/avatar/avatar.component.tsx +++ b/js/react/lib/components/avatar/avatar.component.tsx @@ -17,21 +17,14 @@ export const Avatar = withAs( return ( - {alt} + {alt} ); } diff --git a/js/react/lib/components/badge/badge.component.tsx b/js/react/lib/components/badge/badge.component.tsx index 60da204..6d41ffd 100644 --- a/js/react/lib/components/badge/badge.component.tsx +++ b/js/react/lib/components/badge/badge.component.tsx @@ -20,13 +20,12 @@ export const Badge = withAs( -
+
{displayValue()} ); diff --git a/js/react/lib/components/badge/badge.const.ts b/js/react/lib/components/badge/badge.const.ts index a09de9d..b7c87a8 100644 --- a/js/react/lib/components/badge/badge.const.ts +++ b/js/react/lib/components/badge/badge.const.ts @@ -1,25 +1,13 @@ export const BADGE_VARIANTS = { - completed: [ - "bg-success-100 text-success-600 [&>div]:bg-success-600", - "dark:bg-success-950 dark:text-success-400 [&>div]:bg-success-600", - ], - reading: [ - "bg-warning-100 text-warning-500 [&>div]:bg-warning-500", - "dark:bg-warning-950 dark:text-warning-300 [&>div]:bg-warning-300", - ], - pending: [ - "bg-error-100 text-error-600 [&>div]:bg-error-600", - "dark:bg-error-950 dark:text-error-300 [&>div]:bg-error-300", - ], - unread: [ - "bg-neutral-100 text-neutral-500 [&>div]:bg-neutral-500", - "dark:bg-neutral-950 dark:text-neutral-300 [&>div]:bg-neutral-300", - ], + completed: "rustlanges-badge--variant-completed", + reading: "rustlanges-badge--variant-reading", + pending: "rustlanges-badge--variant-pending", + unread: "rustlanges-badge--variant-unread", }; export const BADGE_TYPE = { - default: "[&>span]:hidden size-4 px-0! justify-center", - numeric: "flex-row-reverse ", + default: "rustlanges-badge--type-default", + numeric: "rustlanges-badge--type-numeric", text: undefined, }; diff --git a/js/react/lib/components/button/button.component.tsx b/js/react/lib/components/button/button.component.tsx index 99d31cb..bbee347 100644 --- a/js/react/lib/components/button/button.component.tsx +++ b/js/react/lib/components/button/button.component.tsx @@ -16,9 +16,8 @@ export const Button = withAs((Component, props: ButtonProps) => { return ( svg]:size-6", + variants[variant], + "text-button rustlanges-button", className )} {...attr} diff --git a/js/react/lib/components/button/button.const.ts b/js/react/lib/components/button/button.const.ts index c71344e..aaf58aa 100644 --- a/js/react/lib/components/button/button.const.ts +++ b/js/react/lib/components/button/button.const.ts @@ -1,31 +1,8 @@ export const variants = { - primary: [ - "border rounded-2xl", - "bg-primary-500 border-black text-black shadow-rb-black", - "dark:bg-primary-300", - "hover:bg-primary-600 dark:hover:bg-primary-400 active:shadow-none", - "disabled:bg-neutral-100 disabled:shadow-none disabled:border-neutral-400 disabled:text-neutral-400", - "dark:disabled:bg-neutral-950", - ], - secondary: [ - "border rounded-2xl", - "bg-light text-neutral-950 border-neutral-950 shadow-rb-neutral-950", - "dark:bg-dark dark:text-light dark:border-light dark:shadow-rb-neutral-50", - "hover:shadow-rb-primary-500 hover:border-primary-500 hover:text-primary-500", - "disabled:bg-neutral-100 disabled:text-neutral-400 disabled:border-neutral-400! disabled:shadow-none", - "dark:disabled:bg-neutral-950", - "active:shadow-none", - ], - text: [ - "text-neutral-950 hover:text-primary-600", - "dark:text-light dark:hover:text-primary-300", - ], - icon: [ - "rounded-full border aspect-square p-2! !h-fit", - "bg-light border-black text-black", - "dark:bg-dark dark:border-light dark:text-light", - "hover:text-primary-500 hover:border-primary-500", - ], + primary: "rustlanges-button--primary", + secondary: "rustlanges-button--secondary", + text: "rustlanges-button--text", + icon: "rustlanges-button--icon", }; export type ButtonVariants = keyof typeof variants; diff --git a/js/react/lib/components/chip/chip.component.tsx b/js/react/lib/components/chip/chip.component.tsx index d8b6833..893d505 100644 --- a/js/react/lib/components/chip/chip.component.tsx +++ b/js/react/lib/components/chip/chip.component.tsx @@ -12,12 +12,7 @@ export const Chip = (props: ChipProps) => { const { label, variant = "featured", className, ...attr } = props; return (
svg]:size-3.5", - className - )} + className={cn(variants[variant], "rustlanges-chip", className)} {...attr} > {icons[variant] ? React.createElement(icons[variant]) : null} diff --git a/js/react/lib/components/chip/chip.const.ts b/js/react/lib/components/chip/chip.const.ts index 7312437..33aaaee 100644 --- a/js/react/lib/components/chip/chip.const.ts +++ b/js/react/lib/components/chip/chip.const.ts @@ -1,41 +1,11 @@ import { Location, StarBold } from "@/icons"; export const variants = { - featured: [ - "border rounded-[20px]", - "bg-primary-400 border-black text-black", - "min-h-[32px]", - "text-sm", - "p-[4px] px-[12px]", - ], - numeric: [ - "border rounded-[20px]", - "bg-primary-200 border-black text-black", - "min-h-[32px]", - "text-sm", - "p-[4px] px-[12px]", - ], - description: [ - "border rounded-[20px]", - "bg-secondary-200 border-black text-black", - "min-h-[32px]", - "text-sm", - "p-[4px] px-[12px]", - ], - location: [ - "border rounded-[20px]", - "bg-secondary-200 border-black text-black", - "min-h-[24px]", - "text-sm", - "p-[2px] px-[12px]", - ], - small: [ - "border rounded-[20px]", - "bg-secondary-200 border-black text-black", - "min-h-[22px]", - "text-xs", - "p-[2px] px-[8px]", - ], + featured: "rustlanges-chip--featured", + numeric: "rustlanges-chip--numeric", + description: "rustlanges-chip--description", + location: "rustlanges-chip--location", + small: "rustlanges-chip--small", }; export type ChipVariants = keyof typeof variants; diff --git a/js/react/lib/components/collaborators/collaborators.component.tsx b/js/react/lib/components/collaborators/collaborators.component.tsx index 7594d87..ceaf5ba 100644 --- a/js/react/lib/components/collaborators/collaborators.component.tsx +++ b/js/react/lib/components/collaborators/collaborators.component.tsx @@ -24,8 +24,8 @@ export const Collaborators = ({ const hasMaxCollaborators = numberOfCollaborators > MAX_COLLABORATORS; const extraCollaborators = numberOfCollaborators - MAX_COLLABORATORS; return ( -
-
+
+
{collaborators.slice(0, MAX_COLLABORATORS).map((collaborator, idx) => { const space = idx ? 12 : 0; return ( diff --git a/js/react/lib/components/dropdown/dropdown.component.tsx b/js/react/lib/components/dropdown/dropdown.component.tsx index 4581629..d213dbf 100644 --- a/js/react/lib/components/dropdown/dropdown.component.tsx +++ b/js/react/lib/components/dropdown/dropdown.component.tsx @@ -23,37 +23,32 @@ export const DropdownState = ({ value, onChange }: DropdownStateProps) => { const Icon = open ? ArrowUp : ArrowDown; return ( -
+
{open && ( -
    +
      {DROPDOWN_OPTIONS.map(opt => (
    • handleSelect(opt.value)} > diff --git a/js/react/lib/components/flap/flap.component.tsx b/js/react/lib/components/flap/flap.component.tsx index e413835..bb6237f 100644 --- a/js/react/lib/components/flap/flap.component.tsx +++ b/js/react/lib/components/flap/flap.component.tsx @@ -10,24 +10,12 @@ type FlapProps = { export const Flap = ({ label, variant, className, ...rest }: FlapProps) => { const Icon = FLAP_ICONS[variant]; return ( -
      +
      { svg]:h-3 [&>svg]:w-3", + "rustlanges-flap__view", + !!Icon && "rustlanges-flap__view--icon", ])} > {Icon ? : null} - + {label} diff --git a/js/react/lib/components/flap/flap.const.ts b/js/react/lib/components/flap/flap.const.ts index f3866e3..126b14f 100644 --- a/js/react/lib/components/flap/flap.const.ts +++ b/js/react/lib/components/flap/flap.const.ts @@ -1,9 +1,9 @@ import { StarBold } from "@/icons"; export const FLAP_VARIANTS = { - highlight: "text-primary-400", - numeric: "text-primary-200", - descriptive: "text-secondary-400", + highlight: "rustlanges-flap--highlight", + numeric: "rustlanges-flap--numeric", + descriptive: "rustlanges-flap--descriptive", }; export const FLAP_ICONS = { diff --git a/js/react/lib/components/level/level.component.tsx b/js/react/lib/components/level/level.component.tsx index c63a333..06897c3 100644 --- a/js/react/lib/components/level/level.component.tsx +++ b/js/react/lib/components/level/level.component.tsx @@ -12,12 +12,7 @@ export const Level = withAs( return ( {LEVEL_LABELS[variant]} diff --git a/js/react/lib/components/level/level.const.ts b/js/react/lib/components/level/level.const.ts index 92b6023..b28e691 100644 --- a/js/react/lib/components/level/level.const.ts +++ b/js/react/lib/components/level/level.const.ts @@ -1,8 +1,8 @@ export const LEVEL_VARIANTS = { - n1: "bg-primary-100", - n2: "bg-primary-300", - n3: "bg-primary-500", - op: "bg-secondary-400", + n1: "rustlanges-level--n1", + n2: "rustlanges-level--n2", + n3: "rustlanges-level--n3", + op: "rustlanges-level--op", }; export const LEVEL_LABELS = { diff --git a/js/react/lib/components/radio/radio.component.tsx b/js/react/lib/components/radio/radio.component.tsx index 69fb219..60af7b4 100644 --- a/js/react/lib/components/radio/radio.component.tsx +++ b/js/react/lib/components/radio/radio.component.tsx @@ -6,15 +6,7 @@ type RadioProps = InputHTMLAttributes; export const Radio = ({ className, ...rest }: RadioProps) => { return ( diff --git a/js/react/lib/components/tag/tag.component.tsx b/js/react/lib/components/tag/tag.component.tsx index 5639f4c..8c5be97 100644 --- a/js/react/lib/components/tag/tag.component.tsx +++ b/js/react/lib/components/tag/tag.component.tsx @@ -1,6 +1,5 @@ import { withAs } from "@/utils/hoc"; import { cn } from "@/utils/tw-merge"; -import { TAG_VARIANTS } from "./tag.const"; type TagProps = { label?: string; @@ -13,8 +12,8 @@ export const Tag = withAs( return ( = theme(--breakpoint-sm)) { - padding-left: calc((100vw + 16px - 640px) / 2); - padding-right: calc((100vw + 16px - 640px) / 2); - } - - @media (width >= theme(--breakpoint-md)) { - padding-left: calc((100vw + 16px - 768px) / 2); - padding-right: calc((100vw + 16px - 768px) / 2); - } - - @media (width >= theme(--breakpoint-lg)) { - padding-left: calc((100vw + 16px - 1024px) / 2); - padding-right: calc((100vw + 16px - 1024px) / 2); - } - - @media (width >= theme(--breakpoint-xl)) { - padding-left: calc((100vw + 16px - 1280px) / 2); - padding-right: calc((100vw + 16px - 1280px) / 2); - } - - @media (width >= theme(--breakpoint-2xl)) { - padding-left: calc((100vw + 16px - 1536px) / 2); - padding-right: calc((100vw + 16px - 1536px) / 2); - } -} - -@custom-variant mobile (@media (max-width: 767px)); - -@layer components { - .text-h1 { - font-size: 32px; - font-weight: 700; - line-height: 125%; - letter-spacing: 0.32%; - - @apply desktop:text-[48px]; - } - - .text-h2 { - font-size: 32px; - font-weight: 700; - line-height: 140%; - letter-spacing: 0.24%; - - @apply desktop:text-[32px]; - } - - .text-h3 { - font-size: 24px; - font-weight: 600; - line-height: 150%; - letter-spacing: 0.2%; - - @apply desktop:text-[28px]; - } - - .text-h4 { - font-size: 18px; - font-weight: 600; - line-height: 160%; - letter-spacing: 0.18%; - - @apply desktop:text-[24px]; - } - - .text-h5 { - font-size: 16px; - font-weight: 500; - line-height: 160%; - letter-spacing: 0.08%; - - @apply desktop:text-[20px]; - } - - .text-h6 { - font-size: 14px; - font-weight: 500; - line-height: 160%; - letter-spacing: 0.07%; - - @apply desktop:text-[18px]; - } - - .text-subtitle-1 { - font-size: 16px; - line-height: 175%; - letter-spacing: 0.08%; - - @apply desktop:text-[20px]; - } - - .text-subtitle-2 { - font-size: 14px; - font-weight: 500; - line-height: 160%; - letter-spacing: 0.08%; - - @apply desktop:text-[16px]; - } - - .text-paragraph-1 { - font-size: 14px; - line-height: 160%; - letter-spacing: 0; - - @apply desktop:text-[16px]; - } - - .text-paragraph-2 { - font-size: 12px; - line-height: 150%; - letter-spacing: 0; - - @apply desktop:text-[14px]; - } - - .text-button { - font-size: 14px; - font-weight: 600; - line-height: 160%; - letter-spacing: 0.28%; - @apply desktop:text-[16px]; - } - - .text-caption { - font-size: 12px; - line-height: 150%; - letter-spacing: 0.06%; - } - - .text-overline { - font-size: 10px; - font-weight: 600; - line-height: 150%; - letter-spacing: 1%; - } - - .heading { - font-size: 28px; - font-weight: 700; - line-height: 125%; - letter-spacing: 0.32%; - - @apply desktop:text-[40px]; - } -} - -@layer utilities { - @supports not selector(::-webkit-scrollbar) { - .scrollbar { - scrollbar-color: var(--color-neutral-300) var(--color-neutral-100); - - @variant dark { - scrollbar-color: var(--color-neutral-900) var(--color-neutral-600); - } - } - } - - .scrollbar::-webkit-scrollbar { - @apply w-4; - } - - .scrollbar::-webkit-scrollbar-track { - @apply rounded-full bg-neutral-100 dark:bg-neutral-900; - } - - .scrollbar::-webkit-scrollbar-thumb { - @apply rounded-full bg-neutral-300 transition dark:bg-neutral-600; - } - .scrollbar::-webkit-scrollbar-thumb:hover { - @apply opacity-90; - } -} +@import "@rustlanges/styles"; diff --git a/js/react/package.json b/js/react/package.json index 76a1571..4decec3 100644 --- a/js/react/package.json +++ b/js/react/package.json @@ -34,6 +34,7 @@ }, "devDependencies": { "@eslint/js": "^9.28.0", + "@rustlanges/styles": "file:../../styles", "@tailwindcss/cli": "^4.1.8", "@tailwindcss/vite": "^4.1.8", "@types/node": "^22.15.29", diff --git a/js/react/tsconfig.app.json b/js/react/tsconfig.app.json index 7e00afd..83f561d 100644 --- a/js/react/tsconfig.app.json +++ b/js/react/tsconfig.app.json @@ -20,7 +20,7 @@ // Path aliases "baseUrl": "./lib", "paths": { - "@/*": ["./*"], + "@/*": ["./*"] }, /* Linting */ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e8cbf4e..5fa8586 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,6 +27,9 @@ importers: '@eslint/js': specifier: ^9.28.0 version: 9.28.0 + '@rustlanges/styles': + specifier: file:../../styles + version: link:../../styles '@tailwindcss/cli': specifier: ^4.1.8 version: 4.1.8 @@ -88,6 +91,15 @@ importers: specifier: ^4.5.4 version: 4.5.4(@types/node@22.15.29)(rollup@4.41.1)(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1)) + styles: + devDependencies: + '@tailwindcss/cli': + specifier: ^4.1.8 + version: 4.1.8 + tailwindcss: + specifier: ^4.1.8 + version: 4.1.8 + packages: '@ampproject/remapping@2.3.0': diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index bc681d9..fc52176 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,6 @@ packages: - js/react + - styles onlyBuiltDependencies: - "@parcel/watcher" - "@swc/core" diff --git a/styles/.gitignore b/styles/.gitignore new file mode 100644 index 0000000..69192d0 --- /dev/null +++ b/styles/.gitignore @@ -0,0 +1,3 @@ +node_modules/ + +dist/ diff --git a/styles/README.md b/styles/README.md new file mode 100644 index 0000000..e2af02e --- /dev/null +++ b/styles/README.md @@ -0,0 +1,63 @@ +# RustLangES Design System styles + +### Installation + +> [!WARNING] +> Both deploys are pending and subject to change. + +```bash +$ npm install @rustlanges/styles +``` + +or by cdn + +```html + +``` + +## Usage + +### Using tailwindcss + +In your tailwindcss's styles file import `@rustlanges/styles`, or import just +the modules needed. + + +```css +/* For complete theme */ +@import "@rustlanges/styles"; + +/* For modular theme */ +@import "@rustlanges/styles/theme"; +@import "@rustlanges/styles/breakpoints"; +@import "@rustlanges/styles/components"; +@import "@rustlanges/styles/utilities"; + +@import "@rustlanges/styles/components/text"; +@import "@rustlanges/styles/utilities/shadow"; +``` + +> [!NOTE] +> Importing `@rustlanges/styles` also import default theme from tailwindcss +> `tailwindcss/theme` and `tailwindcss/utilities` but don't reset styles. + +### Using vite: + +```js +// With tailwindcss installed +import "@rustlanges/styles"; + +// Without tailwindcss installed +import "@rustlanges/styles/bundled.css"; +``` + +> [!NOTE] +> Just import component styles and some utilities classes defined in [safelist.txt](./safelist.txt). + +## Project structure + +``` +. +├── components/ +└── utilities/ +``` diff --git a/styles/breakpoints.css b/styles/breakpoints.css new file mode 100644 index 0000000..f6fcc66 --- /dev/null +++ b/styles/breakpoints.css @@ -0,0 +1 @@ +@custom-variant mobile (@media (max-width: 767px)); diff --git a/styles/components.css b/styles/components.css new file mode 100644 index 0000000..dc9ae68 --- /dev/null +++ b/styles/components.css @@ -0,0 +1,11 @@ +@import "./components/avatar.css"; +@import "./components/badge.css"; +@import "./components/button.css"; +@import "./components/chip.css"; +@import "./components/collaborators.css"; +@import "./components/dropdown.css"; +@import "./components/flap.css"; +@import "./components/level.css"; +@import "./components/radio.css"; +@import "./components/tag.css"; +@import "./components/text.css"; diff --git a/styles/components/avatar.css b/styles/components/avatar.css new file mode 100644 index 0000000..909499a --- /dev/null +++ b/styles/components/avatar.css @@ -0,0 +1,9 @@ +@layer components { + .rustlanges-avatar { + @apply grid aspect-square place-items-center overflow-hidden rounded-full border object-cover; + } + + .rustlanges-avatar__img { + @apply aspect-square size-full; + } +} diff --git a/styles/components/badge.css b/styles/components/badge.css new file mode 100644 index 0000000..5d9abd8 --- /dev/null +++ b/styles/components/badge.css @@ -0,0 +1,50 @@ +@layer components { + .rustlanges-badge { + @apply flex w-fit items-center gap-1 rounded-full border-[0.8px] border-black px-2; + + font-size: 10px; + @variant desktop { + font-size: 12px; + } + } + + .rustlanges-badge__dot { + @apply size-1 rounded-full; + } + + .rustlanges-badge--type-default { + @apply px-0! size-4 justify-center [&>span]:hidden; + } + + .rustlanges-badge--type-numeric { + @apply flex-row-reverse; + } + + .rustlanges-badge--variant-completed { + @apply bg-success-100 text-success-600 [&>div]:bg-success-600; + @variant dark { + @apply bg-success-950 text-success-400 [&>div]:bg-success-600; + } + } + + .rustlanges-badge--variant-reading { + @apply bg-warning-100 text-warning-500 [&>div]:bg-warning-500; + @variant dark { + @apply bg-warning-950 text-warning-300 [&>div]:bg-warning-300; + } + } + + .rustlanges-badge--variant-pending { + @apply bg-error-100 text-error-600 [&>div]:bg-error-600; + @variant dark { + @apply bg-error-950 text-error-300 [&>div]:bg-error-300; + } + } + + .rustlanges-badge--variant-unread { + @apply bg-neutral-100 text-neutral-500 [&>div]:bg-neutral-500; + @variant dark { + @apply bg-neutral-950 text-neutral-300 [&>div]:bg-neutral-300; + } + } +} diff --git a/styles/components/button.css b/styles/components/button.css new file mode 100644 index 0000000..2337a24 --- /dev/null +++ b/styles/components/button.css @@ -0,0 +1,63 @@ +@layer components { + .rustlanges-button { + @apply flex h-12 w-fit cursor-pointer items-center justify-center gap-2.5 px-8 transition [&>svg]:size-6; + + @variant disabled { + @apply cursor-not-allowed; + } + } + + .rustlanges-button--primary { + @apply rounded-2xl border; + @apply bg-primary-500 shadow-rb-black border-black text-black; + @apply hover:bg-primary-600 active:shadow-none; + + @variant disabled { + @apply border-neutral-400 bg-neutral-100 text-neutral-400 shadow-none; + } + + @variant dark { + @apply bg-primary-300 hover:bg-primary-400 disabled:bg-neutral-950; + } + } + + .rustlanges-button--secondary { + @apply rounded-2xl border; + @apply bg-light shadow-rb-neutral-950 border-neutral-950 text-neutral-950; + @apply active:shadow-none; + + @variant disabled { + @apply border-neutral-400! bg-neutral-100 text-neutral-400 shadow-none; + } + + @variant hover { + @apply shadow-rb-primary-500 border-primary-500 text-primary-500; + } + + @variant dark { + @apply bg-dark text-light border-light shadow-rb-neutral-50; + @apply disabled:bg-neutral-950; + } + } + + .rustlanges-button--text { + @apply hover:text-primary-600 text-neutral-950; + + @variant dark { + @apply text-light hover:text-primary-300; + } + } + + .rustlanges-button--icon { + @apply p-2! aspect-square !h-fit rounded-full border; + @apply bg-light border-black text-black; + + @variant hover { + @apply text-primary-500 border-primary-500; + } + + @variant dark { + @apply bg-dark border-light text-light; + } + } +} diff --git a/styles/components/chip.css b/styles/components/chip.css new file mode 100644 index 0000000..6c53cb3 --- /dev/null +++ b/styles/components/chip.css @@ -0,0 +1,46 @@ +@layer components { + .rustlanges-chip { + @apply flex w-fit cursor-default items-center justify-center gap-1 transition; + @apply [&>svg]:size-3.5; + } + + .rustlanges-chip--featured { + @apply rounded-[20px] border; + @apply bg-primary-400 border-black text-black; + @apply min-h-[32px]; + @apply text-sm; + @apply p-[4px] px-[12px]; + } + + .rustlanges-chip--numeric { + @apply rounded-[20px] border; + @apply bg-primary-200 border-black text-black; + @apply min-h-[32px]; + @apply text-sm; + @apply p-[4px] px-[12px]; + } + + .rustlanges-chip--description { + @apply rounded-[20px] border; + @apply bg-secondary-200 border-black text-black; + @apply min-h-[32px]; + @apply text-sm; + @apply p-[4px] px-[12px]; + } + + .rustlanges-chip--location { + @apply rounded-[20px] border; + @apply bg-secondary-200 border-black text-black; + @apply min-h-[24px]; + @apply text-sm; + @apply p-[2px] px-[12px]; + } + + .rustlanges-chip--small { + @apply rounded-[20px] border; + @apply bg-secondary-200 border-black text-black; + @apply min-h-[22px]; + @apply text-xs; + @apply p-[2px] px-[8px]; + } +} diff --git a/styles/components/collaborators.css b/styles/components/collaborators.css new file mode 100644 index 0000000..9fa9284 --- /dev/null +++ b/styles/components/collaborators.css @@ -0,0 +1,9 @@ +@layer components { + .rustlanges-collaborators { + @apply flex h-12 w-full items-center justify-between; + } + + .rustlanges-collaborators__avatars { + @apply flex w-fit items-center; + } +} diff --git a/styles/components/dropdown.css b/styles/components/dropdown.css new file mode 100644 index 0000000..7c88597 --- /dev/null +++ b/styles/components/dropdown.css @@ -0,0 +1,45 @@ +@layer components { + .rustlanges-dropdown { + @apply relative grid w-fit; + } + + .rustlanges-dropdown__view { + @apply shadow-rb-black flex h-6 items-center gap-1 overflow-hidden rounded-sm border border-black; + @apply text-[12px]; + } + + .rustlanges-dropdown__view-dot { + @apply ml-2 size-1 rounded-full; + } + + .rustlanges-dropdown__view-icon { + @apply size-6 rounded-r-sm border-l border-l-black; + @apply bg-white text-black; + + @variant dark { + @apply bg-dark text-neutral-50; + } + } + + .rustlanges-dropdown__content { + @apply absolute left-0 top-full mt-2 w-full transition duration-200; + } + + .rustlanges-dropdown__content--open { + @apply visible opacity-100; + } + + .rustlanges-dropdown__content--closed { + @apply invisible opacity-0; + } + + .rustlanges-dropdown__list { + @apply shadow-rb-black grid gap-1.5 px-2 py-1.5 transition; + @apply rounded-sm border border-black; + @apply dark:bg-dark bg-white; + } + + .rustlanges-dropdown__list-item { + @apply cursor-pointer; + } +} diff --git a/styles/components/flap.css b/styles/components/flap.css new file mode 100644 index 0000000..f8b8647 --- /dev/null +++ b/styles/components/flap.css @@ -0,0 +1,40 @@ +@layer components { + .rustlanges-flap { + @apply relative flex justify-center gap-2; + @apply h-6 w-20 px-5; + + @variant desktop { + @apply h-[47.5px] w-[167.5px] px-8; + } + } + + .rustlanges-flap__svg { + @apply desktop:px-3 absolute left-0 top-0 z-0 h-full w-full px-1; + } + + .rustlanges-flap--highlight { + @apply text-primary-400; + } + + .rustlanges-flap--numeric { + @apply text-primary-200; + } + + .rustlanges-flap--descriptive { + @apply text-secondary-400; + } + + .rustlanges-flap__view { + @apply z-10 flex h-fit w-full items-center justify-center gap-2 text-center font-medium text-neutral-950; + @apply desktop:pt-1; + @apply [&>svg]:h-3 [&>svg]:w-3; + } + + .rustlanges-flap__view--icon { + @apply desktop:*:even:block pt-[3px] *:even:hidden; + } + + .rustlanges-flap__view-text { + @apply desktop:pt-0 line-clamp-1 pt-px; + } +} diff --git a/styles/components/level.css b/styles/components/level.css new file mode 100644 index 0000000..96e82d9 --- /dev/null +++ b/styles/components/level.css @@ -0,0 +1,22 @@ +@layer components { + .rustlanges-level { + @apply rounded-xl border border-black px-2 leading-[150%]; + @apply desktop:text-sm text-xxs; + } + + .rustlanges-level--n1 { + @apply bg-primary-100; + } + + .rustlanges-level--n2 { + @apply bg-primary-300; + } + + .rustlanges-level--n3 { + @apply bg-primary-500; + } + + .rustlanges-level--op { + @apply bg-secondary-400; + } +} diff --git a/styles/components/radio.css b/styles/components/radio.css new file mode 100644 index 0000000..0d965ad --- /dev/null +++ b/styles/components/radio.css @@ -0,0 +1,13 @@ +@layer components { + .rustlanges-radio { + @apply shadow-rb-black aspect-square appearance-none transition; + @apply flex size-4 items-center justify-center rounded-full border border-black; + @apply dark:bg-dark bg-white; + @apply checked:after:bg-primary-500; + + @variant after { + @apply absolute size-2 rounded-full transition; + @apply bg-gray dark:bg-neutral-500; + } + } +} diff --git a/styles/components/tag.css b/styles/components/tag.css new file mode 100644 index 0000000..740d08f --- /dev/null +++ b/styles/components/tag.css @@ -0,0 +1,20 @@ +@layer components { + .rustlanges-tag { + @apply grid h-7 cursor-pointer place-items-center rounded-[20px] border px-2 text-xs font-semibold transition; + } + + .rustlanges-tag--default { + @apply bg-light border-black text-black; + + @variant dark { + @apply border-neutral-50 bg-neutral-950 text-neutral-50; + } + } + .rustlanges-tag--selected { + @apply bg-secondary-100 border-secondary-600 text-secondary-600; + + @variant dark { + @apply bg-primary-950 border-primary-500 text-primary-500; + } + } +} diff --git a/styles/components/text.css b/styles/components/text.css new file mode 100644 index 0000000..178afdc --- /dev/null +++ b/styles/components/text.css @@ -0,0 +1,119 @@ +@layer components { + .text-h1 { + font-size: 32px; + font-weight: 700; + line-height: 125%; + letter-spacing: 0.32%; + + @apply desktop:text-[48px]; + } + + .text-h2 { + font-size: 32px; + font-weight: 700; + line-height: 140%; + letter-spacing: 0.24%; + + @apply desktop:text-[32px]; + } + + .text-h3 { + font-size: 24px; + font-weight: 600; + line-height: 150%; + letter-spacing: 0.2%; + + @apply desktop:text-[28px]; + } + + .text-h4 { + font-size: 18px; + font-weight: 600; + line-height: 160%; + letter-spacing: 0.18%; + + @apply desktop:text-[24px]; + } + + .text-h5 { + font-size: 16px; + font-weight: 500; + line-height: 160%; + letter-spacing: 0.08%; + + @apply desktop:text-[20px]; + } + + .text-h6 { + font-size: 14px; + font-weight: 500; + line-height: 160%; + letter-spacing: 0.07%; + + @apply desktop:text-[18px]; + } + + .text-subtitle-1 { + font-size: 16px; + line-height: 175%; + letter-spacing: 0.08%; + + @apply desktop:text-[20px]; + } + + .text-subtitle-2 { + font-size: 14px; + font-weight: 500; + line-height: 160%; + letter-spacing: 0.08%; + + @apply desktop:text-[16px]; + } + + .text-paragraph-1 { + font-size: 14px; + line-height: 160%; + letter-spacing: 0; + + @apply desktop:text-[16px]; + } + + .text-paragraph-2 { + font-size: 12px; + line-height: 150%; + letter-spacing: 0; + + @apply desktop:text-[14px]; + } + + .text-button { + font-size: 14px; + font-weight: 600; + line-height: 160%; + letter-spacing: 0.28%; + + @apply desktop:text-[16px]; + } + + .text-caption { + font-size: 12px; + line-height: 150%; + letter-spacing: 0.06%; + } + + .text-overline { + font-size: 10px; + font-weight: 600; + line-height: 150%; + letter-spacing: 1%; + } + + .heading { + font-size: 28px; + font-weight: 700; + line-height: 125%; + letter-spacing: 0.32%; + + @apply desktop:text-[40px]; + } +} diff --git a/styles/package.json b/styles/package.json new file mode 100644 index 0000000..82f7787 --- /dev/null +++ b/styles/package.json @@ -0,0 +1,43 @@ +{ + "name": "@rustlanges/styles", + "private": false, + "version": "0.0.1", + "type": "module", + "exports": { + ".": "./tailwindcss.css", + "./bundled.css": "./dist/bundled.css", + "./breakpoints": "./breakpoints.css", + "./components": "./components.css", + "./tailwindcss": "./tailwindcss.css", + "./theme": "./theme.css", + "./utilities": "./utilities.css", + "./components/*": "./components/*.css", + "./utilities/*": "./utilities/*.css" + }, + "files": [ + "dist", + "components", + "utilities", + "breakpoints.css", + "components.css", + "package.json", + "safelist.txt", + "tailwindcss.css", + "theme.css", + "utilities.css" + ], + "repository": { + "type": "git", + "url": "https://github.com/RustLangES/design-system-components", + "directory": "styles" + }, + "scripts": { + "build": "npx @tailwindcss/cli -i tailwindcss.css -o dist/bundled.css --minify" + }, + "peerDependencies": {}, + "devDependencies": { + "@tailwindcss/cli": "^4.1.8", + "tailwindcss": "^4.1.8" + }, + "dependencies": {} +} diff --git a/styles/safelist.txt b/styles/safelist.txt new file mode 100644 index 0000000..23144b2 --- /dev/null +++ b/styles/safelist.txt @@ -0,0 +1 @@ +shadow-rb-black diff --git a/styles/tailwindcss.css b/styles/tailwindcss.css new file mode 100644 index 0000000..a27a068 --- /dev/null +++ b/styles/tailwindcss.css @@ -0,0 +1,10 @@ +@layer theme, base, components, utilities; + +@import "tailwindcss/theme.css" layer(theme); +@import "tailwindcss/utilities.css" layer(utilities); + +@import "./theme.css"; + +@import "./breakpoints.css"; +@import "./components.css"; +@import "./utilities.css"; diff --git a/styles/theme.css b/styles/theme.css new file mode 100644 index 0000000..8e96562 --- /dev/null +++ b/styles/theme.css @@ -0,0 +1,140 @@ +@theme static { + /* ----- Breakpoints ----- */ + --breakpoint-desktop: 360px; + + /* ------ Colors ------ */ + --color-primary-50: #fff6ed; + --color-primary-100: #ffebd4; + --color-primary-200: #ffd2a8; + --color-primary-300: #ffb270; + --color-primary-400: #ff8637; + --color-primary-500: #ff6e1f; + --color-primary-600: #f04906; + --color-primary-700: #c63407; + --color-primary-800: #9e2a0e; + --color-primary-900: #7f260f; + --color-primary-950: #450f05; + + --color-secondary-50: #f4f3ff; + --color-secondary-100: #ebe9fe; + --color-secondary-200: #d9d6fe; + --color-secondary-300: #bcb5fd; + --color-secondary-400: #9a8afb; + --color-secondary-500: #7a5bf7; + --color-secondary-600: #6637ee; + --color-secondary-700: #5927da; + --color-secondary-800: #3e1c96; + --color-secondary-900: #3e1c96; + --color-secondary-950: #240f66; + + --color-neutral-50: #f6f6f6; + --color-neutral-100: #e7e7e7; + --color-neutral-200: #d1d1d1; + --color-neutral-300: #b0b0b0; + --color-neutral-400: #888888; + --color-neutral-500: #6d6d6d; + --color-neutral-600: #5d5d5d; + --color-neutral-700: #4f4f4f; + --color-neutral-800: #454545; + --color-neutral-900: #3d3d3d; + --color-neutral-950: #222222; + + --color-error-50: #fff1f1; + --color-error-100: #fee5e5; + --color-error-200: #fdced2; + --color-error-300: #fba6ac; + --color-error-400: #f87480; + --color-error-500: #f04257; + --color-error-600: #dd2140; + --color-error-700: #ba1636; + --color-error-800: #9c1533; + --color-error-900: #851632; + --color-error-950: #4a0717; + + --color-warning-50: #fdf7e9; + --color-warning-100: #faebc7; + --color-warning-200: #f7d591; + --color-warning-300: #f0b042; + --color-warning-400: #eb9a24; + --color-warning-500: #dc8316; + --color-warning-600: #bd6211; + --color-warning-700: #974411; + --color-warning-800: #7d3816; + --color-warning-900: #6b2e18; + --color-warning-950: #3e160a; + + --color-success-50: #effef5; + --color-success-100: #dafee9; + --color-success-200: #b8fad4; + --color-success-300: #80f5b4; + --color-success-400: #48e78f; + --color-success-500: #19ce6b; + --color-success-600: #0eab55; + --color-success-700: #0f8646; + --color-success-800: #12693a; + --color-success-900: #115632; + --color-success-950: #03301a; + + --color-light: #fafafa; + --color-dark: #2e2e2e; + --color-gray: #d9d9d9; + + /* Fonts */ + --text-xxs: 10px; + --text-caption: 12px; + --text-caption--font-weight: 400; + --text-caption--letter-spacing: 0em; + --text-caption--line-height: 16px; + --text-caption-bold: 12px; + --text-caption-bold--font-weight: 500; + --text-caption-bold--letter-spacing: 0em; + --text-caption-bold--line-height: 16px; + --text-body: 14px; + --text-body--font-weight: 400; + --text-body--letter-spacing: 0em; + --text-body--line-height: 20px; + --text-body-bold: 14px; + --text-body-bold--font-weight: 500; + --text-body-bold--letter-spacing: 0em; + --text-body-bold--line-height: 20px; + --text-heading-3: 18px; + --text-heading-3--font-weight: 500; + --text-heading-3--letter-spacing: 0em; + --text-heading-3--line-height: 20px; + --text-heading-2: 24px; + --text-heading-2--font-weight: 500; + --text-heading-2--letter-spacing: 0em; + --text-heading-2--line-height: 24px; + --text-heading-1: 32px; + --text-heading-1--font-weight: 500; + --text-heading-1--letter-spacing: 0em; + --text-heading-1--line-height: 36px; + --text-monospace-body: 14px; + --text-monospace-body--font-weight: 400; + --text-monospace-body--letter-spacing: 0em; + --text-monospace-body--line-height: 20px; + + /* Font families */ + --font-caption: Inter; + --font-caption-bold: Inter; + --font-body: Inter; + --font-body-bold: Inter; + --font-heading-3: Inter; + --font-heading-2: Inter; + --font-heading-1: Inter; + --font-monospace-body: monospace; + + /* Border radiuses */ + --radius-sm: 8px; + --radius-md: 16px; + --radius-DEFAULT: 16px; + --radius-lg: 24px; + --radius-full: 9999px; + + /* Spacing */ + --spacing-112: 28rem; + --spacing-144: 36rem; + --spacing-192: 48rem; + --spacing-256: 64rem; + --spacing-320: 80rem; +} diff --git a/styles/utilities.css b/styles/utilities.css new file mode 100644 index 0000000..e54e1f1 --- /dev/null +++ b/styles/utilities.css @@ -0,0 +1,3 @@ +@import "./utilities/container.css"; +@import "./utilities/scollbar.css"; +@import "./utilities/shadow.css"; diff --git a/styles/utilities/container.css b/styles/utilities/container.css new file mode 100644 index 0000000..e9e2da3 --- /dev/null +++ b/styles/utilities/container.css @@ -0,0 +1,29 @@ +@utility container { + padding-left: 16px; + padding-right: 16px; + + @media (width >= theme(--breakpoint-sm)) { + padding-left: calc((100vw + 16px - 640px) / 2); + padding-right: calc((100vw + 16px - 640px) / 2); + } + + @media (width >= theme(--breakpoint-md)) { + padding-left: calc((100vw + 16px - 768px) / 2); + padding-right: calc((100vw + 16px - 768px) / 2); + } + + @media (width >= theme(--breakpoint-lg)) { + padding-left: calc((100vw + 16px - 1024px) / 2); + padding-right: calc((100vw + 16px - 1024px) / 2); + } + + @media (width >= theme(--breakpoint-xl)) { + padding-left: calc((100vw + 16px - 1280px) / 2); + padding-right: calc((100vw + 16px - 1280px) / 2); + } + + @media (width >= theme(--breakpoint-2xl)) { + padding-left: calc((100vw + 16px - 1536px) / 2); + padding-right: calc((100vw + 16px - 1536px) / 2); + } +} diff --git a/styles/utilities/scrollbar.css b/styles/utilities/scrollbar.css new file mode 100644 index 0000000..75a391e --- /dev/null +++ b/styles/utilities/scrollbar.css @@ -0,0 +1,26 @@ +@layer utilities { + @supports not selector(::-webkit-scrollbar) { + .scrollbar { + scrollbar-color: var(--color-neutral-300) var(--color-neutral-100); + + @variant dark { + scrollbar-color: var(--color-neutral-900) var(--color-neutral-600); + } + } + } + + .scrollbar::-webkit-scrollbar { + @apply w-4; + } + + .scrollbar::-webkit-scrollbar-track { + @apply rounded-full bg-neutral-100 dark:bg-neutral-900; + } + + .scrollbar::-webkit-scrollbar-thumb { + @apply rounded-full bg-neutral-300 transition dark:bg-neutral-600; + } + .scrollbar::-webkit-scrollbar-thumb:hover { + @apply opacity-90; + } +} diff --git a/styles/utilities/shadow.css b/styles/utilities/shadow.css new file mode 100644 index 0000000..ef35839 --- /dev/null +++ b/styles/utilities/shadow.css @@ -0,0 +1,6 @@ +@utility shadow-rb-* { + box-shadow: 1px 1px 0 0 --value(--color- *); + @media (min-width: 360px) { + box-shadow: 2px 2px 0 0 --value(--color- *); + } +}