Skip to content

Instantly share code, notes, and snippets.

@easylogic
Last active February 1, 2025 16:53
Show Gist options
  • Save easylogic/96364bfaaae04b1f611f0a7eebd62893 to your computer and use it in GitHub Desktop.
Save easylogic/96364bfaaae04b1f611f0a7eebd62893 to your computer and use it in GitHub Desktop.
GL - Graphic Language

document, page, gl.component, gl.componentSet, variant, template

@document "Enterprise Design System" {
  description: "Enterprise application design system";
  version: "2.0.0";

  @variables {
    colors: {
      light: {
        primary: {
          50: #F0F9FF;
          100: #E0F2FE;
          200: #BAE6FD;
          300: #7DD3FC;
          400: #38BDF8;
          500: #0EA5E9;
          600: #0284C7;
          700: #0369A1;
        }
        neutral: {
          50: #F9FAFB;
          100: #F3F4F6;
          200: #E5E7EB;
          300: #D1D5DB;
          400: #9CA3AF;
          500: #6B7280;
          600: #4B5563;
          700: #374151;
          800: #1F2937;
          900: #111827;
        }
        success: {
          50: #ECFDF5;
          500: #10B981;
          700: #047857;
        }
        error: {
          50: #FEF2F2;
          500: #EF4444;
          700: #B91C1C;
        }
      }
      dark: {
        primary: {
          50: #082F49;
          100: #0C4A6E;
          200: #075985;
          300: #0369A1;
          400: #0284C7;
          500: #0EA5E9;
          600: #38BDF8;
          700: #7DD3FC;
        }
        neutral: {
          50: #18181B;
          100: #27272A;
          200: #3F3F46;
          300: #52525B;
          400: #71717A;
          500: #A1A1AA;
          600: #D4D4D8;
          700: #E4E4E7;
          800: #F4F4F5;
          900: #FAFAFA;
        }
      }
    }

    spacing: {
      base: {
        xs: 4;
        sm: 8;
        md: 16;
        lg: 24;
        xl: 32;
        xxl: 48;
      }
    }

    typography: {
      base: {
        heading: {
          h1: {
            size: 36;
            lineHeight: 44;
            weight: 700;
            tracking: -0.02;
          }
          h2: {
            size: 30;
            lineHeight: 38;
            weight: 600;
            tracking: -0.01;
          }
          h3: {
            size: 24;
            lineHeight: 32;
            weight: 600;
          }
        }
        body: {
          large: {
            size: 18;
            lineHeight: 28;
            weight: 400;
          }
          base: {
            size: 16;
            lineHeight: 24;
            weight: 400;
          }
          small: {
            size: 14;
            lineHeight: 20;
            weight: 400;
          }
        }
      }
    }

    radius: {
      base: {
        sm: 4;
        md: 6;
        lg: 8;
        xl: 12;
        full: 9999;
      }
    }
  }

  @page "Foundation" {
    @componentSet Typography {
      @config {
        modes: {
          colors: light;
        }
      }

      @component variant=h1 {
        @template {
          <text
            value="Heading 1"
            fontSize={token(typography.heading.h1.size)}
            lineHeight={token(typography.heading.h1.lineHeight)}
            fontWeight={token(typography.heading.h1.weight)}
            letterSpacing={token(typography.heading.h1.tracking)}
            color={token(colors.neutral.900)}
          />
        }
      }

      @component variant=body {
        @template {
          <text
            value="Body text"
            fontSize={token(typography.body.base.size)}
            lineHeight={token(typography.body.base.lineHeight)}
            fontWeight={token(typography.body.base.weight)}
            color={token(colors.neutral.700)}
          />
        }
      }
    }
  }

  @page "Components" {
    @componentSet Button {
      @config {
        modes: {
          colors: light;
        }
      }

      @props {
        variant: primary | secondary | ghost = primary;
        size: sm | md | lg = md;
      }

      @component variant=primary,size=md {
        @template {
          <frame
            display="flex"
            alignItems="center"
            justifyContent="center"
            height={40}
            paddingLeft={token(spacing.md)}
            paddingRight={token(spacing.md)}
            backgroundColor={token(colors.primary.500)}
            borderRadius={token(radius.md)}
          >
            <text
              value="Button"
              fontSize={token(typography.body.base.size)}
              fontWeight={500}
              color={token(colors.neutral.50)}
            />
          </frame>
        }
      }

      @component variant=secondary,size=md {
        @template {
          <frame
            display="flex"
            alignItems="center"
            justifyContent="center"
            height={40}
            paddingLeft={token(spacing.md)}
            paddingRight={token(spacing.md)}
            backgroundColor={token(colors.neutral.100)}
            borderRadius={token(radius.md)}
          >
            <text
              value="Button"
              fontSize={token(typography.body.base.size)}
              fontWeight={500}
              color={token(colors.neutral.700)}
            />
          </frame>
        }
      }
    }

    @component Card {
      @config {
        modes: {
          colors: light;
        }
      }

      @template {
        <frame
          display="flex"
          flexDirection="column"
          width={320}
          backgroundColor={token(colors.neutral.50)}
          borderRadius={token(radius.lg)}
        >
          <frame
            padding={token(spacing.md)}
            borderBottom="1px solid"
            borderColor={token(colors.neutral.200)}
          >
            <text
              value="Card Title"
              fontSize={token(typography.body.large.size)}
              fontWeight={600}
              color={token(colors.neutral.900)}
            />
          </frame>
          <frame padding={token(spacing.md)}>
            <text
              value="Card content goes here with some sample text."
              fontSize={token(typography.body.base.size)}
              lineHeight={token(typography.body.base.lineHeight)}
              color={token(colors.neutral.700)}
            />
          </frame>
        </frame>
      }
    }
  }

  @page "Assets" {
    @assets {
      @image Logo {
        source: "./assets/logo.svg";
        format: "svg";
        size: {
          width: 120;
          height: 40;
        }
      }

      @media LoadingSpinner {
        type: "sequence";
        source: "./assets/loading/*.png";
        frameCount: 30;
        fps: 60;
      }
    }
  }
}
/**
 * @description Main document
 * @version 1.0.0
 */
@document "My Design System" {
  description: "A comprehensive design system example";
  version: "1.0.0";

  // Global variables
  @variables {
    // Core color tokens
    colors {
      light {
        primary: #007AFF;
        secondary: #5856D6;
        background: rgb(255, 255, 255);
        text: rgba(0, 0, 0, 0.9);
        accent: hsl(210, 100%, 50%);
      }
      dark {
        primary: #0A84FF;
        secondary: #5E5CE6;
        background: rgb(28, 28, 30);
        text: rgba(255, 255, 255, 0.9);
      }
    }

    // Typography
    typography {
      base {
        fontFamily: "Inter";
        fontSize: 16px;
        lineHeight: 1.5;
      }
    }
  }

  // Configuration
  @config {
    collections: {
      themes: {
        light: true;
        dark: false;
      }
    }
    breakpoints: {
      mobile: 320px;
      tablet: 768px;
      desktop: 1024px;
    }
  }

  // Assets
  @assets {
    @image logo {
      source: "./assets/logo.png";
      format: "png";
      size: {
        width: 200;
        height: 60;
      }
    }

    @media intro-animation {
      type: "sequence";
      source: "./assets/intro/*.png";
      frameCount: 60;
      fps: 30;
    }
  }

  // Component imports
  @import "./components/atoms.sa";
  @import "./components/molecules.sa";

  /**
 * Button component set with variants
 */
@componentSet Button {
  @props {
    variant: "primary" | "secondary" | "ghost" = "primary";
    size: "small" | "medium" | "large" = "medium";
    state: "default" | "hover" | "pressed" | "disabled" = "default";
  }

  // Primary small button in different states
  @component "variant=primary,size=small,state=default" {
    @template {
      <button className="button-primary-small">Button</button>
    }
  }

  @component "variant=primary,size=small,state=hover" {
    @template {
      <button className="button-primary-small hover">Button</button>
    }
  }

  // Secondary medium buttons
  @component "variant=secondary,size=medium,state=default" {
    @template {
      <button className="button-secondary-medium">Button</button>
    }
  }

  @component "variant=secondary,size=medium,state=disabled" {
    @template {
      <button className="button-secondary-medium disabled">Button</button>
    }
  }

  // Ghost large buttons
  @component "variant=ghost,size=large,state=default" {
    @template {
      <button className="button-ghost-large">Button</button>
    }
  }

  @component "variant=ghost,size=large,state=pressed" {
    @template {
      <button className="button-ghost-large pressed">Button</button>
    }
  }
}

  // Component set example
  @componentSet TextField {
    @props {
      label: string;
      placeholder: string = "";
      type: "text" | "password" | "email" = "text";
      value: string;
      error: string;
    }

    // Input component
    @component Input {
      @template {
        <input
          type={props.type}
          value={props.value}
          placeholder={props.placeholder}
          className={`input ${props.error ? 'input--error' : ''}`}
        />
      }
    }

    // Label component
    @component Label {
      @template {
        <label className="label">
          {props.label}
        </label>
      }
    }

    // Error message component
    @component Error {
      @template {
        {props.error && (
          <span className="error-message">
            {props.error}
          </span>
        )}
      }
    }
  }
}

Graphic Language

그래픽 툴의 무거운 자료형을 언어를 사용하여 심플하게 구성하고 공유한다.

@gl.componentSet Description {
          name: "Description";
          description: "Description text component";

          @props {
            size: sm | md | lg = md;
          }

          @component size=md {
            @template {
              <text
                fontFamily="Inter"
                fontSize="token(typography.description.md.fontSize)"
                fontWeight="token(typography.description.md.fontWeight)"
                color="token(colors.text.secondary)"
                lineHeight="token(typography.description.md.lineHeight)">
                {slot.children}
              </text>
            }
          }
}
@easylogic
Copy link
Author

계속 업그레이드 중

@tokens {
  colors(light, dark) {    // collection(mode1, mode2)

    light {
      semantic {
        primary: #007AFF;
        secondary: #5856D6;
      }
    }

    dark {
      semantic {
        primary: #007AFF;
        secondary: #5856D6;
      }
    }

  }

  semantic {
    foreground: colors.semantic.primary;
    background: colors.semantic.secondary;
  }
}



@component Button {

  @props {
    variant: primary | secondary = primary;
    mode: light | dark = light;
  }

  @template target=figma {

    @styles slot {
      root(colors=light) {
        background: colors.semantic.primary;
      }

      label(colors=dark, typography=compact) {
        color: colors.semantic.primary;
        font: typography.body;
      }

    }

    <Frame slot="root">
      <Text slot="label">Button</Text>
    </Frame>
  }

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment