Procházet zdrojové kódy

DS button CSS and component implementation plus move most --ciam variables to --ds

GitOrigin-RevId: 5dd6b490a6f597892b47a89aabce748cea3e3bc6
Tim Down před 11 měsíci
rodič
revize
c0c3bfe185

+ 60 - 0
services/web/frontend/js/shared/components/ds/ds-button.tsx

@@ -0,0 +1,60 @@
+import { forwardRef, ReactNode } from 'react'
+import { Button, ButtonProps } from 'react-bootstrap'
+
+type DSButtonProps = Pick<
+  ButtonProps,
+  | 'children'
+  | 'disabled'
+  | 'href'
+  | 'id'
+  | 'target'
+  | 'rel'
+  | 'onClick'
+  | 'onMouseDown'
+  | 'onMouseOver'
+  | 'onMouseOut'
+  | 'onFocus'
+  | 'onBlur'
+  | 'size'
+  | 'active'
+  | 'type'
+> & {
+  leadingIcon?: ReactNode
+  trailingIcon?: ReactNode
+  variant?: 'primary' | 'secondary' | 'tertiary' | 'danger'
+}
+
+const DSButton = forwardRef<HTMLButtonElement, DSButtonProps>(
+  (
+    {
+      children,
+      leadingIcon,
+      trailingIcon,
+      variant = 'primary',
+      size,
+      ...props
+    },
+    ref
+  ) => {
+    return (
+      <Button
+        className="d-inline-grid btn-ds"
+        variant={variant}
+        size={size}
+        {...props}
+        ref={ref}
+        role={undefined}
+      >
+        <span className="button-content">
+          {leadingIcon}
+          {children}
+          {trailingIcon}
+        </span>
+      </Button>
+    )
+  }
+)
+
+DSButton.displayName = 'DSButton'
+
+export default DSButton

+ 37 - 0
services/web/frontend/stories/shared/ds-button.stories.tsx

@@ -0,0 +1,37 @@
+import { Meta } from '@storybook/react'
+import { figmaDesignUrl } from '../../../.storybook/utils/figma-design-url'
+import DSButton from '@/shared/components/ds/ds-button'
+
+type Args = React.ComponentProps<typeof DSButton>
+
+export const Button = (args: Args) => {
+  return <DSButton {...args} />
+}
+
+const meta: Meta<typeof DSButton> = {
+  title: 'Shared / Components / DS Button',
+  component: DSButton,
+  args: {
+    children: 'Button',
+  },
+  argTypes: {
+    size: {
+      control: 'radio',
+      options: ['lg', 'md', 'sm'],
+    },
+    variant: {
+      control: 'radio',
+      options: ['primary', 'secondary', 'tertiary', 'danger'],
+    },
+  },
+  parameters: {
+    controls: {
+      include: ['children', 'disabled', 'size', 'variant'],
+    },
+    ...figmaDesignUrl(
+      'https://www.figma.com/design/aJQlecvqCS9Ry8b6JA1lQN/DS---Components?node-id=4565-2932&m=dev'
+    ),
+  },
+}
+
+export default meta

+ 3 - 2
services/web/frontend/stylesheets/abstracts/mixins.scss

@@ -21,7 +21,8 @@
   $borderless: true,
   $disabled-color: $content-disabled,
   $disabled-background: $bg-light-disabled,
-  $disabled-border: $bg-light-disabled
+  $disabled-border: $disabled-background,
+  $active-background: $hover-background
 ) {
   --bs-btn-color: #{$color};
   --bs-btn-bg: #{$background};
@@ -30,7 +31,7 @@
   --bs-btn-hover-bg: #{$hover-background};
   --bs-btn-hover-border-color: #{$hover-border};
   --bs-btn-active-color: #{$color};
-  --bs-btn-active-bg: #{$hover-background};
+  --bs-btn-active-bg: #{$active-background};
   --bs-btn-active-border-color: #{$hover-border};
   --bs-btn-disabled-color: #{$disabled-color};
   --bs-btn-disabled-bg: #{$disabled-background};

+ 1 - 3
services/web/frontend/stylesheets/ciam/all.scss

@@ -1,5 +1,3 @@
-@import 'ciam-colors';
+@import '../ds/all'; // DS design system styles
 @import 'ciam-layout';
-@import 'ciam-mixins';
-@import 'ciam-spacing';
 @import 'ciam-variables';

+ 0 - 68
services/web/frontend/stylesheets/ciam/ciam-colors.scss

@@ -1,68 +0,0 @@
-.ciam-enabled {
-  --ciam-color-neutral-50: #fafafa;
-  --ciam-color-neutral-100: #f2f2f2;
-  --ciam-color-neutral-200: #e6e6e6;
-  --ciam-color-neutral-300: #d6d6d6;
-  --ciam-color-neutral-400: #c7c7c7;
-  --ciam-color-neutral-500: #b5b5b5;
-  --ciam-color-neutral-600: #a1a1a1;
-  --ciam-color-neutral-700: #8a8a8a;
-  --ciam-color-neutral-800: #6b6b6b;
-  --ciam-color-neutral-900: #383838;
-  --ciam-color-neutral-950: #262626;
-  --ciam-color-green-50: #f2f8f5;
-  --ciam-color-green-100: #e3f2eb;
-  --ciam-color-green-200: #c0e7d6;
-  --ciam-color-green-300: #8adbb7;
-  --ciam-color-green-400: #38cc89;
-  --ciam-color-green-500: #26b072;
-  --ciam-color-green-600: #158954;
-  --ciam-color-green-700: #19754c;
-  --ciam-color-green-800: #196241;
-  --ciam-color-green-900: #164630;
-  --ciam-color-green-950: #112c20;
-  --ciam-color-yellow-50: #fffaeb;
-  --ciam-color-yellow-100: #fff7db;
-  --ciam-color-yellow-200: #ffeeb8;
-  --ciam-color-yellow-300: #ffe58f;
-  --ciam-color-yellow-400: #ffda61;
-  --ciam-color-yellow-500: #ffcc20;
-  --ciam-color-yellow-600: #f0b800;
-  --ciam-color-yellow-700: #d1a000;
-  --ciam-color-yellow-800: #ad8500;
-  --ciam-color-yellow-900: #806200;
-  --ciam-color-yellow-950: #574200;
-  --ciam-color-red-50: #fff5f7;
-  --ciam-color-red-100: #fee7eb;
-  --ciam-color-red-200: #fdc9d3;
-  --ciam-color-red-300: #fba7b7;
-  --ciam-color-red-400: #f97b92;
-  --ciam-color-red-500: #f51d43;
-  --ciam-color-red-600: #e60a32;
-  --ciam-color-red-700: #c3092b;
-  --ciam-color-red-800: #a10723;
-  --ciam-color-red-900: #75051a;
-  --ciam-color-red-950: #530412;
-  --ciam-color-blue-50: #f7fafd;
-  --ciam-color-blue-100: #ecf2f9;
-  --ciam-color-blue-200: #d4e3f2;
-  --ciam-color-blue-300: #bdd4ea;
-  --ciam-color-blue-400: #a2c3e2;
-  --ciam-color-blue-500: #7facd7;
-  --ciam-color-blue-600: #5893cb;
-  --ciam-color-blue-700: #3470a8;
-  --ciam-color-blue-800: #2b5d8c;
-  --ciam-color-blue-900: #1e4161;
-  --ciam-color-blue-950: #17314a;
-  --ciam-color-teal-50: #f1f8f8;
-  --ciam-color-teal-100: #e3f2f1;
-  --ciam-color-teal-200: #c1e2df;
-  --ciam-color-teal-300: #9ed1cd;
-  --ciam-color-teal-400: #6dbab4;
-  --ciam-color-teal-500: #4a9d96;
-  --ciam-color-teal-600: #438e88;
-  --ciam-color-teal-700: #3b7d77;
-  --ciam-color-teal-800: #2f6460;
-  --ciam-color-teal-900: #244c49;
-  --ciam-color-teal-950: #193432;
-}

+ 16 - 18
services/web/frontend/stylesheets/ciam/ciam-layout.scss

@@ -1,18 +1,16 @@
-@import 'ciam-mixins';
-
 .ciam-layout {
-  padding: var(--ciam-spacing-350);
+  padding: var(--ds-spacing-350);
   display: flex;
   min-height: 100vh;
   flex-direction: column;
 
-  @include ciam-body-md-regular;
+  @include ds-body-md-regular;
 }
 
 .ciam-enabled {
-  font-family: var(--ciam-font-family-sans), sans-serif;
-  color: var(--ciam-color-text-primary);
-  font-size: var(--ciam-font-size-400);
+  font-family: var(--ds-font-family-sans), sans-serif;
+  color: var(--ds-color-text-primary);
+  font-size: var(--ds-font-size-400);
   line-height: 1.5;
 
   .ciam-container {
@@ -25,48 +23,48 @@
     background-size: contain;
     height: 64px;
     width: 130px;
-    margin: var(--ciam-spacing-350) auto;
+    margin: var(--ds-spacing-350) auto;
     display: block;
 
     @include media-breakpoint-up(sm) {
-      margin: var(--ciam-spacing-350) var(--ciam-spacing-800);
+      margin: var(--ds-spacing-350) var(--ds-spacing-800);
     }
   }
 
   h1 {
-    @include ciam-heading-sm-semibold;
+    @include ds-heading-sm-semibold;
   }
 
   .ciam-card {
     box-shadow:
       0 4px 6px -4px rgb(0 0 0 / 10%),
       0 1px 29px -3px rgb(0 0 0 / 16%);
-    padding: var(--ciam-spacing-800) var(--ciam-spacing-400);
-    border-radius: var(--ciam-border-radius-400);
+    padding: var(--ds-spacing-800) var(--ds-spacing-400);
+    border-radius: var(--ds-border-radius-400);
     max-width: 460px;
-    margin: var(--ciam-spacing-400) auto;
+    margin: var(--ds-spacing-400) auto;
 
     @include media-breakpoint-up(sm) {
-      padding: var(--ciam-spacing-1300);
+      padding: var(--ds-spacing-1300);
     }
   }
 
   footer {
     display: flex;
-    gap: var(--ciam-spacing-600);
+    gap: var(--ds-spacing-600);
     text-transform: uppercase;
     justify-content: center;
-    margin: var(--ciam-spacing-350) auto;
+    margin: var(--ds-spacing-350) auto;
 
     @include media-breakpoint-up(sm) {
-      margin: var(--ciam-spacing-350) var(--ciam-spacing-800);
+      margin: var(--ds-spacing-350) var(--ds-spacing-800);
       justify-content: start;
     }
 
     a {
       text-decoration: none;
 
-      @include ciam-body-sm-regular;
+      @include ds-body-sm-regular;
     }
   }
 }

+ 0 - 107
services/web/frontend/stylesheets/ciam/ciam-mixins.scss

@@ -1,107 +0,0 @@
-@mixin ciam-body-xs-regular() {
-  font-size: 0.75rem;
-  font-weight: 400;
-  line-height: 1.25rem;
-}
-
-@mixin ciam-body-xs-semibold() {
-  font-size: 0.75rem;
-  font-weight: 600;
-  line-height: 1.25rem;
-}
-
-@mixin ciam-body-sm-regular() {
-  font-size: 0.875rem;
-  font-weight: 400;
-  line-height: 1.25rem;
-}
-
-@mixin ciam-body-sm-semibold() {
-  font-size: 0.875rem;
-  font-weight: 600;
-  line-height: 1.25rem;
-}
-
-@mixin ciam-body-md-regular() {
-  font-size: 1rem;
-  font-weight: 400;
-  line-height: 1.5rem;
-}
-
-@mixin ciam-body-md-semibold() {
-  font-size: 1rem;
-  font-weight: 600;
-  line-height: 1.5rem;
-}
-
-@mixin ciam-body-lg-regular() {
-  font-size: 1.125rem;
-  font-weight: 400;
-  line-height: 1.75rem;
-}
-
-@mixin ciam-body-lg-semibold() {
-  font-size: 1.125rem;
-  font-weight: 600;
-  line-height: 1.75rem;
-}
-
-@mixin ciam-heading-xs-regular() {
-  font-size: 1.125rem;
-  font-weight: 400;
-  line-height: 1.5rem;
-}
-
-@mixin ciam-heading-xs-semibold() {
-  font-size: 1.125rem;
-  font-weight: 600;
-  line-height: 1.5rem;
-}
-
-@mixin ciam-heading-sm-regular() {
-  font-size: 1.25rem;
-  font-weight: 400;
-  line-height: 1.75rem;
-}
-
-@mixin ciam-heading-sm-semibold() {
-  font-size: 1.25rem;
-  font-weight: 600;
-  line-height: 1.75rem;
-}
-
-@mixin ciam-heading-md-regular() {
-  font-size: 1.5rem;
-  font-weight: 400;
-  line-height: 2rem;
-}
-
-@mixin ciam-heading-md-semibold() {
-  font-size: 1.5rem;
-  font-weight: 600;
-  line-height: 2rem;
-}
-
-@mixin ciam-heading-lg-regular() {
-  font-size: 2rem;
-  font-weight: 400;
-  line-height: 2.5rem;
-}
-
-@mixin ciam-heading-lg-semibold() {
-  font-size: 2rem;
-  font-weight: 600;
-  line-height: 2.5rem;
-}
-
-@mixin ciam-heading-xl-regular() {
-  font-size: 2.5rem;
-  font-weight: 400;
-  line-height: 3rem;
-}
-
-@mixin ciam-heading-xl-semibold() {
-  font-size: 2.5rem;
-  font-weight: 600;
-  line-height: 3rem;
-}

+ 0 - 66
services/web/frontend/stylesheets/ciam/ciam-spacing.scss

@@ -1,66 +0,0 @@
-.ciam-enabled {
-  --ciam-font-weight-regular: 400;
-  --ciam-font-weight-medium: 500;
-  --ciam-font-weight-semibold: 600;
-  --ciam-font-weight-bold: 700;
-  --ciam-font-family-sans: inter, sans-serif;
-  --ciam-spacing-50: 2px;
-  --ciam-spacing-100: 4px;
-  --ciam-spacing-150: 6px;
-  --ciam-spacing-200: 8px;
-  --ciam-spacing-250: 10px;
-  --ciam-spacing-300: 12px;
-  --ciam-spacing-350: 14px;
-  --ciam-spacing-400: 16px;
-  --ciam-spacing-500: 20px;
-  --ciam-spacing-600: 24px;
-  --ciam-spacing-700: 28px;
-  --ciam-spacing-800: 32px;
-  --ciam-spacing-900: 36px;
-  --ciam-spacing-1000: 40px;
-  --ciam-spacing-1100: 44px;
-  --ciam-spacing-1200: 48px;
-  --ciam-spacing-1300: 52px;
-  --ciam-spacing-1400: 56px;
-  --ciam-spacing-1500: 60px;
-  --ciam-spacing-1600: 64px;
-  --ciam-spacing-1700: 68px;
-  --ciam-spacing-1800: 72px;
-  --ciam-spacing-1900: 76px;
-  --ciam-spacing-2000: 80px;
-  --ciam-spacing-2100: 84px;
-  --ciam-spacing-2200: 88px;
-  --ciam-spacing-2300: 92px;
-  --ciam-spacing-2400: 96px;
-  --ciam-base-unit: 4px;
-  --ciam-font-size-300: 12px;
-  --ciam-font-size-350: 14px;
-  --ciam-font-size-400: 16px;
-  --ciam-font-size-450: 18px;
-  --ciam-font-size-500: 20px;
-  --ciam-font-size-600: 24px;
-  --ciam-font-size-700: 28px;
-  --ciam-font-size-800: 32px;
-  --ciam-font-size-1000: 40px;
-  --ciam-font-size-1400: 56px;
-  --ciam-font-size-1800: 72px;
-  --ciam-font-line-height-400: 16px;
-  --ciam-font-line-height-500: 20px;
-  --ciam-font-line-height-600: 24px;
-  --ciam-font-line-height-700: 28px;
-  --ciam-font-line-height-800: 32px;
-  --ciam-font-line-height-900: 36px;
-  --ciam-font-line-height-1000: 40px;
-  --ciam-font-line-height-1200: 48px;
-  --ciam-font-line-height-1600: 64px;
-  --ciam-font-line-height-1800: 72px;
-  --ciam-border-width-25: 1px;
-  --ciam-border-width-50: 2px;
-  --ciam-border-radius-50: 2px;
-  --ciam-border-radius-100: 4px;
-  --ciam-border-radius-200: 8px;
-  --ciam-border-radius-300: 12px;
-  --ciam-border-radius-400: 16px;
-  --ciam-border-radius-600: 24px;
-  --ciam-border-radius-full: 9999px;
-}

+ 2 - 6
services/web/frontend/stylesheets/ciam/ciam-variables.scss

@@ -1,17 +1,13 @@
 // TODO: Replace `fuchsia` by the correct colors.
 
 .ciam-enabled {
-  // Base variables
-  --ciam-color-text-secondary: var(--ciam-color-neutral-800);
-  --ciam-color-text-primary: var(--ciam-color-neutral-900);
-
   // Links
   // used in services/web/frontend/stylesheets/base/links.scss
-  --link-color: var(--ciam-color-text-secondary);
+  --link-color: var(--ds-color-text-secondary);
   --link-hover-color: fuchsia;
 
   // TODO: validate that this is correct
-  --link-visited-color: var(--ciam-color-text-secondary);
+  --link-visited-color: var(--ds-color-text-secondary);
   --link-color-dark: fuchsia;
   --link-hover-color-dark: fuchsia;
   --link-visited-color-dark: fuchsia;

+ 7 - 0
services/web/frontend/stylesheets/ds/all.scss

@@ -0,0 +1,7 @@
+@import 'colors';
+@import 'typography';
+@import 'spacing';
+@import 'border';
+@import 'theme';
+@import 'mixins';
+@import 'components/all';

+ 13 - 0
services/web/frontend/stylesheets/ds/border.scss

@@ -0,0 +1,13 @@
+:root {
+  --ds-border-width-25: 1px;
+  --ds-border-width-50: 2px;
+
+  // Border radius
+  --ds-border-radius-full: 9999px;
+  --ds-border-radius-50: 2px;
+  --ds-border-radius-100: 4px;
+  --ds-border-radius-200: 8px;
+  --ds-border-radius-300: 12px;
+  --ds-border-radius-400: 16px;
+  --ds-border-radius-600: 24px;
+}

+ 83 - 0
services/web/frontend/stylesheets/ds/colors.scss

@@ -0,0 +1,83 @@
+:root {
+  // Neutral/grey
+  --ds-color-neutral-50: #fafafa;
+  --ds-color-neutral-100: #f2f2f2;
+  --ds-color-neutral-200: #e6e6e6;
+  --ds-color-neutral-300: #d6d6d6;
+  --ds-color-neutral-400: #c7c7c7;
+  --ds-color-neutral-500: #b5b5b5;
+  --ds-color-neutral-600: #a1a1a1;
+  --ds-color-neutral-700: #8a8a8a;
+  --ds-color-neutral-800: #6b6b6b;
+  --ds-color-neutral-900: #383838;
+  --ds-color-neutral-950: #262626;
+
+  // Green
+  --ds-color-green-50: #f2f8f5;
+  --ds-color-green-100: #e3f2eb;
+  --ds-color-green-200: #c0e7d6;
+  --ds-color-green-300: #8adbb7;
+  --ds-color-green-400: #38cc89;
+  --ds-color-green-500: #26b072;
+  --ds-color-green-600: #158954;
+  --ds-color-green-700: #19754c;
+  --ds-color-green-800: #196241;
+  --ds-color-green-900: #164630;
+  --ds-color-green-950: #112c20;
+
+  // Yellow
+  --ds-color-yellow-50: #fffaeb;
+  --ds-color-yellow-100: #fff7db;
+  --ds-color-yellow-200: #ffeeb8;
+  --ds-color-yellow-300: #ffe58f;
+  --ds-color-yellow-400: #ffda61;
+  --ds-color-yellow-500: #ffcc20;
+  --ds-color-yellow-600: #f0b800;
+  --ds-color-yellow-700: #d1a000;
+  --ds-color-yellow-800: #ad8500;
+  --ds-color-yellow-900: #806200;
+  --ds-color-yellow-950: #574200;
+
+  // Red
+  --ds-color-red-50: #fff5f7;
+  --ds-color-red-100: #fee7eb;
+  --ds-color-red-200: #fdc9d3;
+  --ds-color-red-300: #fba7b7;
+  --ds-color-red-400: #f97b92;
+  --ds-color-red-500: #f51d43;
+  --ds-color-red-600: #e60a32;
+  --ds-color-red-700: #c3092b;
+  --ds-color-red-800: #a10723;
+  --ds-color-red-900: #75051a;
+  --ds-color-red-950: #530412;
+
+  // Blue
+  --ds-color-blue-50: #f7fafd;
+  --ds-color-blue-100: #ecf2f9;
+  --ds-color-blue-200: #d4e3f2;
+  --ds-color-blue-300: #bdd4ea;
+  --ds-color-blue-400: #a2c3e2;
+  --ds-color-blue-500: #7facd7;
+  --ds-color-blue-600: #5893cb;
+  --ds-color-blue-700: #3470a8;
+  --ds-color-blue-800: #2b5d8c;
+  --ds-color-blue-900: #1e4161;
+  --ds-color-blue-950: #17314a;
+
+  // Teal
+  --ds-color-teal-50: #f1f8f8;
+  --ds-color-teal-100: #e3f2f1;
+  --ds-color-teal-200: #c1e2df;
+  --ds-color-teal-300: #9ed1cd;
+  --ds-color-teal-400: #6dbab4;
+  --ds-color-teal-500: #4a9d96;
+  --ds-color-teal-600: #438e88;
+  --ds-color-teal-700: #3b7d77;
+  --ds-color-teal-800: #2f6460;
+  --ds-color-teal-900: #244c49;
+  --ds-color-teal-950: #193432;
+
+  // Black and white
+  --ds-color-white: #fff;
+  --ds-color-black: #000;
+}

+ 1 - 0
services/web/frontend/stylesheets/ds/components/all.scss

@@ -0,0 +1 @@
+@import 'button';

+ 81 - 0
services/web/frontend/stylesheets/ds/components/button.scss

@@ -0,0 +1,81 @@
+.btn.btn-ds {
+  --bs-btn-font-family: var(--ds-font-family-sans);
+  --bs-btn-border-radius: var(--ds-border-radius-200);
+
+  &:focus-visible {
+    outline: 2px solid var(--ds-color-yellow-500);
+    outline-offset: 2px;
+    box-shadow: none;
+  }
+
+  // Default size
+  @include ol-button-size(
+    $font-size: var(--ds-font-size-400),
+    $line-height: var(--ds-font-line-height-600),
+    $padding-x: var(--ds-spacing-400),
+    $padding-y: var(--ds-spacing-100)
+  );
+
+  &.btn-lg {
+    @include ol-button-size(
+      $font-size: var(--ds-font-size-400),
+      $line-height: var(--ds-font-line-height-600),
+      $padding-x: var(--ds-spacing-400),
+      $padding-y: var(--ds-spacing-250)
+    );
+  }
+
+  &.btn-sm {
+    @include ol-button-size(
+      $font-size: var(--ds-font-size-350),
+      $line-height: var(--ds-font-line-height-500),
+      $padding-x: var(--ds-spacing-200),
+      $padding-y: var(--ds-spacing-100)
+    );
+  }
+
+  // Variants
+  &.btn-primary {
+    @include ol-button-variant(
+      $color: var(--ds-color-white),
+      $background: var(--ds-color-neutral-950),
+      $hover-background: var(--ds-color-neutral-900),
+      $active-background: var(--ds-color-neutral-800),
+      $disabled-color: var(--ds-color-neutral-700),
+      $disabled-background: var(--ds-color-neutral-100)
+    );
+  }
+
+  &.btn-secondary {
+    @include ol-button-variant(
+      $color: var(--ds-color-neutral-950),
+      $background: var(--ds-color-neutral-200),
+      $hover-background: var(--ds-color-neutral-300),
+      $active-background: var(--ds-color-neutral-400),
+      $disabled-color: var(--ds-color-neutral-700),
+      $disabled-background: var(--ds-color-neutral-100)
+    );
+  }
+
+  &.btn-tertiary {
+    @include ol-button-variant(
+      $color: var(--ds-color-neutral-950),
+      $background: var(--ds-color-white),
+      $hover-background: var(--ds-color-neutral-100),
+      $active-background: var(--ds-color-neutral-200),
+      $disabled-color: var(--ds-color-neutral-700),
+      $disabled-background: var(--ds-color-neutral-100)
+    );
+  }
+
+  &.btn-danger {
+    @include ol-button-variant(
+      $color: var(--ds-color-white),
+      $background: var(--ds-color-red-700),
+      $hover-background: var(--ds-color-red-800),
+      $active-background: var(--ds-color-red-900),
+      $disabled-color: var(--ds-color-neutral-700),
+      $disabled-background: var(--ds-color-neutral-100)
+    );
+  }
+}

+ 109 - 0
services/web/frontend/stylesheets/ds/mixins.scss

@@ -0,0 +1,109 @@
+// Typography mixins for consistent text styles
+
+@mixin ds-body-xs-regular() {
+  font-size: var(--ds-font-size-300);
+  font-weight: var(--ds-font-weight-regular);
+  line-height: var(--ds-font-line-height-500);
+}
+
+@mixin ds-body-xs-semibold() {
+  font-size: var(--ds-font-size-300);
+  font-weight: var(--ds-font-weight-semibold);
+  line-height: var(--ds-font-line-height-500);
+}
+
+@mixin ds-body-sm-regular() {
+  font-size: var(--ds-font-size-350);
+  font-weight: var(--ds-font-weight-regular);
+  line-height: var(--ds-font-line-height-500);
+}
+
+@mixin ds-body-sm-semibold() {
+  font-size: var(--ds-font-size-350);
+  font-weight: var(--ds-font-weight-semibold);
+  line-height: var(--ds-font-line-height-500);
+}
+
+@mixin ds-body-md-regular() {
+  font-size: var(--ds-font-size-400);
+  font-weight: var(--ds-font-weight-regular);
+  line-height: var(--ds-font-line-height-600);
+}
+
+@mixin ds-body-md-semibold() {
+  font-size: var(--ds-font-size-400);
+  font-weight: var(--ds-font-weight-semibold);
+  line-height: var(--ds-font-line-height-600);
+}
+
+@mixin ds-body-lg-regular() {
+  font-size: var(--ds-font-size-450);
+  font-weight: var(--ds-font-weight-regular);
+  line-height: var(--ds-font-line-height-700);
+}
+
+@mixin ds-body-lg-semibold() {
+  font-size: var(--ds-font-size-450);
+  font-weight: var(--ds-font-weight-semibold);
+  line-height: var(--ds-font-line-height-700);
+}
+
+@mixin ds-heading-xs-regular() {
+  font-size: var(--ds-font-size-450);
+  font-weight: var(--ds-font-weight-regular);
+  line-height: var(--ds-font-line-height-600);
+}
+
+@mixin ds-heading-xs-semibold() {
+  font-size: var(--ds-font-size-450);
+  font-weight: var(--ds-font-weight-semibold);
+  line-height: var(--ds-font-line-height-600);
+}
+
+@mixin ds-heading-sm-regular() {
+  font-size: var(--ds-font-size-500);
+  font-weight: var(--ds-font-weight-regular);
+  line-height: var(--ds-font-line-height-700);
+}
+
+@mixin ds-heading-sm-semibold() {
+  font-size: var(--ds-font-size-500);
+  font-weight: var(--ds-font-weight-semibold);
+  line-height: var(--ds-font-line-height-700);
+}
+
+@mixin ds-heading-md-regular() {
+  font-size: var(--ds-font-size-600);
+  font-weight: var(--ds-font-weight-regular);
+  line-height: var(--ds-font-line-height-800);
+}
+
+@mixin ds-heading-md-semibold() {
+  font-size: var(--ds-font-size-600);
+  font-weight: var(--ds-font-weight-semibold);
+  line-height: var(--ds-font-line-height-800);
+}
+
+@mixin ds-heading-lg-regular() {
+  font-size: var(--ds-font-size-800);
+  font-weight: var(--ds-font-weight-regular);
+  line-height: var(--ds-font-line-height-1000);
+}
+
+@mixin ds-heading-lg-semibold() {
+  font-size: var(--ds-font-size-800);
+  font-weight: var(--ds-font-weight-semibold);
+  line-height: var(--ds-font-line-height-1000);
+}
+
+@mixin ds-heading-xl-regular() {
+  font-size: var(--ds-font-size-1000);
+  font-weight: var(--ds-font-weight-regular);
+  line-height: var(--ds-font-line-height-1200);
+}
+
+@mixin ds-heading-xl-semibold() {
+  font-size: var(--ds-font-size-1000);
+  font-weight: var(--ds-font-weight-semibold);
+  line-height: var(--ds-font-line-height-1200);
+}

+ 31 - 0
services/web/frontend/stylesheets/ds/spacing.scss

@@ -0,0 +1,31 @@
+:root {
+  --ds-base-unit: 4px;
+  --ds-spacing-50: 2px;
+  --ds-spacing-100: 4px;
+  --ds-spacing-150: 6px;
+  --ds-spacing-200: 8px;
+  --ds-spacing-250: 10px;
+  --ds-spacing-300: 12px;
+  --ds-spacing-350: 14px;
+  --ds-spacing-400: 16px;
+  --ds-spacing-500: 20px;
+  --ds-spacing-600: 24px;
+  --ds-spacing-700: 28px;
+  --ds-spacing-800: 32px;
+  --ds-spacing-900: 36px;
+  --ds-spacing-1000: 40px;
+  --ds-spacing-1100: 44px;
+  --ds-spacing-1200: 48px;
+  --ds-spacing-1300: 52px;
+  --ds-spacing-1400: 56px;
+  --ds-spacing-1500: 60px;
+  --ds-spacing-1600: 64px;
+  --ds-spacing-1700: 68px;
+  --ds-spacing-1800: 72px;
+  --ds-spacing-1900: 76px;
+  --ds-spacing-2000: 80px;
+  --ds-spacing-2100: 84px;
+  --ds-spacing-2200: 88px;
+  --ds-spacing-2300: 92px;
+  --ds-spacing-2400: 96px;
+}

+ 30 - 0
services/web/frontend/stylesheets/ds/theme.scss

@@ -0,0 +1,30 @@
+:root {
+  // Default to the light theme
+  --ds-color-bg-default: var(--ds-color-white);
+  --ds-color-text-primary: var(--ds-color-neutral-900);
+  --ds-color-text-secondary: var(--ds-color-neutral-800);
+  --ds-color-text-disabled: var(--ds-color-neutral-500);
+  --ds-color-text-danger-default: var(--ds-color-red-700);
+  --ds-color-text-danger-hover: var(--ds-color-red-800);
+  --ds-color-text-warning-default: var(--ds-color-yellow-900);
+  --ds-color-text-warning-hover: var(--ds-color-yellow-950);
+  --ds-color-text-info-default: var(--ds-color-blue-700);
+  --ds-color-text-info-hover: var(--ds-color-blue-800);
+  --ds-color-text-success-default: var(--ds-color-green-700);
+  --ds-color-text-success-hover: var(--ds-color-green-800);
+
+  .ds-theme-dark {
+    --ds-color-bg-default: var(--ds-color-neutral-950);
+    --ds-color-text-primary: var(--ds-color-white);
+    --ds-color-text-secondary: var(--ds-color-neutral-50);
+    --ds-color-text-disabled: var(--ds-color-neutral-500);
+    --ds-color-text-danger-default: var(--ds-color-red-700);
+    --ds-color-text-danger-hover: var(--ds-color-red-800);
+    --ds-color-text-warning-default: var(--ds-color-yellow-900);
+    --ds-color-text-warning-hover: var(--ds-color-yellow-950);
+    --ds-color-text-info-default: var(--ds-color-blue-700);
+    --ds-color-text-info-hover: var(--ds-color-blue-800);
+    --ds-color-text-success-default: var(--ds-color-green-700);
+    --ds-color-text-success-hover: var(--ds-color-green-800);
+  }
+}

+ 34 - 0
services/web/frontend/stylesheets/ds/typography.scss

@@ -0,0 +1,34 @@
+:root {
+  --ds-font-family-sans: 'Inter';
+
+  // Font weight
+  --ds-font-weight-regular: 400;
+  --ds-font-weight-medium: 500;
+  --ds-font-weight-semibold: 600;
+  --ds-font-weight-bold: 700;
+
+  // Font size
+  --ds-font-size-300: 0.75rem; // 12px
+  --ds-font-size-350: 0.875rem; // 14px
+  --ds-font-size-400: 1rem; // 16px
+  --ds-font-size-450: 1.125rem; // 18px
+  --ds-font-size-500: 1.25rem; // 20px
+  --ds-font-size-600: 1.5rem; // 24px
+  --ds-font-size-700: 1.75rem; // 28px
+  --ds-font-size-800: 2rem; // 32px
+  --ds-font-size-1000: 2.5rem; // 40px
+  --ds-font-size-1400: 3.5rem; // 56px
+  --ds-font-size-1800: 4.5rem; // 72px
+
+  // Line height
+  --ds-font-line-height-400: 1rem; // 16px
+  --ds-font-line-height-500: 1.25rem; // 20px
+  --ds-font-line-height-600: 1.5rem; // 24px
+  --ds-font-line-height-700: 1.75rem; // 28px
+  --ds-font-line-height-800: 2rem; // 32px
+  --ds-font-line-height-1000: 2.5rem; // 40px
+  --ds-font-line-height-1200: 3rem; // 48px
+  --ds-font-line-height-1600: 4rem; // 64px
+  --ds-font-line-height-1800: 4.5rem; // 72px
+  --ds-font-line-height-900: 2.25rem; // 36px
+}