Browse Source

feat: add 3 ai components through semi agent

林艳 3 months ago
parent
commit
1795fd3140

+ 117 - 0
packages/semi-foundation/aiCard/aiCard.scss

@@ -0,0 +1,117 @@
+@import './variables.scss'; 
+
+.semi-ai-card-section {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+  color: $color-ai_card_section_default-text-default;
+  font-family: Inter;
+  font-size: $font-ai_card_section_default-fontSize;
+  font-weight: $font-ai_card_section_default-fontWeight;
+
+  &-block {
+      display: flex;
+      flex-direction: column;
+      align-items: flex-start;
+      justify-content: flex-start;
+      border-radius: $radius-ai_card_section_block;
+      padding: 0;
+      box-sizing: border-box;
+      
+      &-header {
+          display: flex;
+          align-items: center;
+          width: 100%;
+          padding-top: $spacing-ai_card_section_block_header-paddingTop;
+          padding-right: $spacing-ai_card_section_block_header-paddingRight;
+          padding-bottom: $spacing-ai_card_section_block_header-paddingBottom;
+          padding-left: $spacing-ai_card_section_block_header-paddingLeft;
+      }
+
+      &-icon {
+          width: $width-ai_card_section_block_icon;
+          height: $height-ai_card_section_block_icon;
+          flex-shrink: 0;
+          margin-right: $spacing-ai_card_section_block_icon-marginRight;
+      }
+
+      &-title {
+          flex-shrink: 0;
+          min-width: $width-ai_card_section_block_title-minWidth;
+      }
+
+      &-footer {
+          margin-top: $spacing-ai_card_section_block_footer-marginTop;
+      }
+  }
+
+  &-default {
+      background: $color-ai_card_section_default-bg-default;
+      border: 1px solid $color-ai_card_section_default-border-default;
+      padding-top: $spacing-ai_card_section_default-paddingTop;
+      padding-right: $spacing-ai_card_section_default-paddingRight;
+      padding-bottom: $spacing-ai_card_section_default-paddingBottom;
+      padding-left: $spacing-ai_card_section_default-paddingLeft;
+      width: $width-ai_card_section_default;
+      height: $height-ai_card_section_default;
+  }
+  &-stroked {
+      background: $color-ai_card_section_stroked-bg-default;
+      padding-top: $spacing-ai_card_section_stroked-paddingTop;
+      padding-right: $spacing-ai_card_section_stroked-paddingRight;
+      padding-bottom: $spacing-ai_card_section_stroked-paddingBottom;
+      padding-left: $spacing-ai_card_section_stroked-paddingLeft;
+      width: $width-ai_card_section_stroked;
+      height: $height-ai_card_section_stroked;
+  }
+  &-filled {
+      background: $color-ai_card_section_filled-bg-default;
+      background-image: $color-ai_card_section_filled-bgImage-default;
+      padding-top: $spacing-ai_card_section_filled-paddingTop;
+      padding-right: $spacing-ai_card_section_filled-paddingRight;
+      padding-bottom: $spacing-ai_card_section_filled-paddingBottom;
+      padding-left: $spacing-ai_card_section_filled-paddingLeft;
+      width: $width-ai_card_section_filled;
+      height: $height-ai_card_section_filled;
+  }
+  &-filled-top {
+      background: $color-ai_card_section_filled_top-bg-default;
+      padding-top: $spacing-ai_card_section_filled_top-paddingTop;
+      padding-right: $spacing-ai_card_section_filled_top-paddingRight;
+      padding-bottom: $spacing-ai_card_section_filled_top-paddingBottom;
+      padding-left: $spacing-ai_card_section_filled_top-paddingLeft;
+      .ai-card-section-block-header {
+          padding-top: $spacing-ai_card_section_block_header-paddingTop;
+          padding-right: $spacing-ai_card_section_block_header-paddingRight;
+          padding-bottom: $spacing-ai_card_section_block_header-paddingBottom;
+          padding-left: $spacing-ai_card_section_block_header-paddingLeft;
+      }
+      .ai-card-section-filled-top-bg {
+          background: $color-ai_card_section_filled_top_bg-bg-default;
+          border-radius: $radius-ai_card_section_filled_top_bg;
+          background-position: center;
+          background-size: cover;
+          background-repeat: no-repeat;
+          overflow: hidden;
+      }
+  }
+  &-separator {
+      flex-grow: 1;
+      border-radius: $radius-ai_card_section_separator;
+      background: $color-ai_card_section_separator-bg-default;
+      padding: $spacing-ai_card_section_separator-padding;
+      overflow: hidden;
+  }
+  &-rectangle {
+      flex-grow: 1;
+      align-self: stretch;
+      background: $color-ai_card_section_rectangle-bg-default;
+      background-image: $color-ai_card_section_rectangle-bgImage-default;
+  }
+}
+
+
+
+  
+  
+  

+ 15 - 0
packages/semi-foundation/aiCard/constants.ts

@@ -0,0 +1,15 @@
+import { BASE_CLASS_PREFIX } from '../base/constants';
+
+const cssClasses = {
+    PREFIX: `${BASE_CLASS_PREFIX}-ai-card-section`,
+};
+
+const strings = {
+    TYPE_SET: ['default', 'stroked', 'filled', 'filled-top'],
+    STATUS_SET: ['normal', 'hover', 'active', 'disabled'],
+};
+
+const numbers = {
+};
+
+export { cssClasses, strings, numbers };

+ 57 - 0
packages/semi-foundation/aiCard/variables.scss

@@ -0,0 +1,57 @@
+// Color
+$color-ai_card_section_default-text-default: var(--semi-color-text-0);
+$color-ai_card_section_default-bg-default: var(--semi-color-white);
+$color-ai_card_section_default-border-default: var(--AI-light-general-1, #ffffff);
+$color-ai_card_section_stroked-bg-default: var(--semi-color-white);
+$color-ai_card_section_filled-bg-default: var(--AI-Light-General-general-0);
+$color-ai_card_section_filled-bgImage-default: linear-gradient(308.66deg, #fff2ff 0%, #f8edff 30%, #f4f4ff 60%, #eff7ff 100%);
+$color-ai_card_section_filled_top-bg-default: var(--semi-color-bg-0);
+$color-ai_card_section_filled_top_bg-bg-default: var(--AI-Light-Background-top-0);
+$color-ai_card_section_separator-bg-default: #fff;
+$color-ai_card_section_rectangle-bg-default: var(--AI-Light-General-general-0);
+$color-ai_card_section_rectangle-bgImage-default: linear-gradient(302.99deg, #fff2ff 0%, #f8edff 30%, #f4f4ff 60%, #eff7ff 100%);
+
+// Width / Height
+$width-ai_card_section_block_icon: 20px;
+$height-ai_card_section_block_icon: 20px;
+$width-ai_card_section_block_title-minWidth: 101px;
+$width-ai_card_section_default: 382px;
+$height-ai_card_section_default: 319px;
+$width-ai_card_section_stroked: 382px;
+$height-ai_card_section_stroked: 320px;
+$width-ai_card_section_filled: 414px;
+$height-ai_card_section_filled: 336px;
+
+// Spacing
+$spacing-ai_card_section_block_header-paddingTop: 24px;
+$spacing-ai_card_section_block_header-paddingRight: 16px;
+$spacing-ai_card_section_block_header-paddingBottom: 24px;
+$spacing-ai_card_section_block_header-paddingLeft: 16px;
+$spacing-ai_card_section_block_icon-marginRight: 8px;
+$spacing-ai_card_section_block_footer-marginTop: auto;
+$spacing-ai_card_section_default-paddingTop: 0;
+$spacing-ai_card_section_default-paddingRight: 23px;
+$spacing-ai_card_section_default-paddingBottom: 23px;
+$spacing-ai_card_section_default-paddingLeft: 23px;
+$spacing-ai_card_section_stroked-paddingTop: 0;
+$spacing-ai_card_section_stroked-paddingRight: 24px;
+$spacing-ai_card_section_stroked-paddingBottom: 24px;
+$spacing-ai_card_section_stroked-paddingLeft: 24px;
+$spacing-ai_card_section_filled-paddingTop: 0;
+$spacing-ai_card_section_filled-paddingRight: 8px;
+$spacing-ai_card_section_filled-paddingBottom: 8px;
+$spacing-ai_card_section_filled-paddingLeft: 8px;
+$spacing-ai_card_section_filled_top-paddingTop: 0;
+$spacing-ai_card_section_filled_top-paddingRight: 0;
+$spacing-ai_card_section_filled_top-paddingBottom: 164px;
+$spacing-ai_card_section_filled_top-paddingLeft: 0;
+$spacing-ai_card_section_separator-padding: 12px;
+
+// Radius
+$radius-ai_card_section_block: 8px;
+$radius-ai_card_section_filled_top_bg: 8px;
+$radius-ai_card_section_separator: 7px;
+
+// Font
+$font-ai_card_section_default-fontSize: 18px;
+$font-ai_card_section_default-fontWeight: 600;

+ 159 - 0
packages/semi-foundation/aiLoading/aiLoading.scss

@@ -0,0 +1,159 @@
+@import './variables.scss';
+
+.semi-loading {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+  line-height: $font-ai_loading_default-lineHeight;
+  color: $color-ai_loading_default-text-default;
+  font-family: Inter;
+  font-size: $font-ai_loading_default-fontSize;
+
+  &-small {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: $width-ai_loading_small-default;
+    text-align: left;
+    letter-spacing: $font-ai_loading_small-letterSpacing;
+
+    &-dots {
+      display: flex;
+      flex-direction: row;
+      flex-shrink: 0;
+      align-items: center;
+      justify-content: space-between;
+      width: $width-ai_loading_small_dots-default;
+      height: $height-ai_loading_small_dots-default;
+
+      &-dot {
+        border-radius: $radius-ai_loading_small_dots-dot;
+        width: $width-ai_loading_small_dots_dot-default;
+        height: $height-ai_loading_small_dots_dot-default;
+        &-1 {
+          background: $color-ai_loading_small_dots-dot1-default;
+        }
+        &-2 {
+          background: $color-ai_loading_small_dots-dot2-default;
+        }
+        &-3 {
+          background: $color-ai_loading_small_dots-dot3-default;
+        }
+      }
+    }
+    &-text {
+      flex-shrink: 0;
+      margin-left: $spacing-ai_loading_small_text-marginLeft;
+      min-width: $width-ai_loading_small_text-minWidth;
+      vertical-align: baseline;
+    }
+  }
+
+  &-large {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    width: $width-ai_loading_large-default;
+    text-align: center;
+    letter-spacing: $font-ai_loading_large-letterSpacing;
+
+    &-dots {
+      display: flex;
+      flex-direction: row;
+      flex-shrink: 0;
+      align-items: center;
+      justify-content: space-between;
+      padding-right: $spacing-ai_loading_large_dots-paddingRight;
+      width: $width-ai_loading_large_dots-default;
+      height: $height-ai_loading_large_dots-default;
+
+      &-dot {
+        border-radius: $radius-ai_loading_large_dots-dot;
+        width: $width-ai_loading_large_dots_dot-default;
+        height: $height-ai_loading_large_dots_dot-default;
+        &-1 {
+          background: $color-ai_loading_large_dots-dot1-default;
+        }
+        &-2 {
+          background: $color-ai_loading_large_dots-dot2-default;
+        }
+        &-3 {
+          background: $color-ai_loading_large_dots-dot3-default;
+        }
+      }
+    }
+    &-track {
+      display: flex;
+      flex-direction: column;
+      flex-shrink: 0;
+      align-items: flex-start;
+      justify-content: flex-start;
+      margin-top: $spacing-ai_loading_large_track-marginTop;
+      border-radius: $radius-ai_loading_large_track-default;
+      background: $color-ai_loading_large_track-bg-default;
+      background-color: $color-ai_loading_large_track-bgcolor-default;
+      width: $width-ai_loading_large_track-default;
+      height: $height-ai_loading_large_track-default;
+      background-image: $color-ai_loading_large_track-bgimage-default;
+
+      &-inner {
+        display: flex;
+        flex-basis: 0;
+        flex-direction: column;
+        flex-grow: 1;
+        align-items: flex-start;
+        justify-content: flex-start;
+        border-radius: $radius-ai_loading_large_track_inner-default;
+        background: $color-ai_loading_large_track_inner-bg-default;
+        width: $width-ai_loading_large_track_inner-default;
+        background-image: $color-ai_loading_large_track_inner-bgimage-default;
+      }
+    }
+    &-info {
+      display: flex;
+      flex-direction: column;
+      flex-shrink: 0;
+      align-items: flex-start;
+      align-self: stretch;
+      justify-content: flex-start;
+      margin-top: $spacing-ai_loading_large_info-marginTop;
+
+      &-title {
+        flex-shrink: 0;
+        align-self: stretch;
+        vertical-align: baseline;
+        line-height: $font-ai_loading_large_info_title-lineHeight;
+        color: $color-ai_loading_large_info_title-text-default;
+        font-size: $font-ai_loading_large_info_title-fontSize;
+        font-weight: $font-ai_loading_large_info_title-fontWeight;
+      }
+
+      &-desc {
+        flex-shrink: 0;
+        align-self: stretch;
+        margin-top: $spacing-ai_loading_large_info_desc-marginTop;
+        vertical-align: baseline;
+        line-height: $font-ai_loading_large_info_desc-lineHeight;
+        color: $color-ai_loading_large_info_desc-text-default;
+        font-size: $font-ai_loading_large_info_desc-fontSize;
+        font-weight: $font-ai_loading_large_info_desc-fontWeight;
+      }
+    }
+  }
+  &-colored {
+    display: inline-flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: $radius-ai_loading_colored-default;
+    padding: $spacing-ai_loading_colored-padding;
+
+    &-icon {
+      flex-shrink: 0;
+      width: $width-ai_loading_colored_icon-default;
+      height: $height-ai_loading_colored_icon-default;
+      overflow: hidden;
+    }
+  }
+}
+

+ 13 - 0
packages/semi-foundation/aiLoading/constants.ts

@@ -0,0 +1,13 @@
+import { BASE_CLASS_PREFIX } from '../base/constants';
+
+const cssClasses = {
+    PREFIX: `${BASE_CLASS_PREFIX}-loading`,
+} as const;
+
+const strings = {
+    TYPE_SET: ['small', 'large', 'colored'],
+} as const;
+
+const numbers = {} as const;
+
+export { cssClasses, strings, numbers };

+ 60 - 0
packages/semi-foundation/aiLoading/variables.scss

@@ -0,0 +1,60 @@
+// COLOR
+$color-ai_loading_default-text-default: var(--semi-color-text-3);
+$color-ai_loading_small_dots-dot1-default: #5338ff;
+$color-ai_loading_small_dots-dot2-default: #b030f0;
+$color-ai_loading_small_dots-dot3-default: #e72dff;
+$color-ai_loading_large_dots-dot1-default: #5338ff;
+$color-ai_loading_large_dots-dot2-default: #b030f0;
+$color-ai_loading_large_dots-dot3-default: #e72dff;
+$color-ai_loading_large_track-bg-default: var(--semi-color-fill-0);
+$color-ai_loading_large_track-bgcolor-default: #00000000;
+$color-ai_loading_large_track-bgimage-default: linear-gradient(#2e32380d, #2e32380d);
+$color-ai_loading_large_track_inner-bg-default: var(--AI-Light-General-general-5);
+$color-ai_loading_large_track_inner-bgimage-default: linear-gradient(271.15deg,#e945ff 0%,#a647ff 30%,#6b61ff 60%,#2e8cff 100%);
+$color-ai_loading_large_info_title-text-default: var(--semi-color-text-0);
+$color-ai_loading_large_info_desc-text-default: var(--semi-color-text-1);
+
+// WIDTH/HEIGHT
+$width-ai_loading_small-default: 119px;
+$width-ai_loading_small_dots-default: 13px;
+$height-ai_loading_small_dots-default: 4px;
+$width-ai_loading_small_dots_dot-default: 3px;
+$height-ai_loading_small_dots_dot-default: 3px;
+$width-ai_loading_small_text-minWidth: 67px;
+$width-ai_loading_large-default: 261px;
+$width-ai_loading_large_dots-default: 24px;
+$height-ai_loading_large_dots-default: 7px;
+$width-ai_loading_large_dots_dot-default: 6px;
+$height-ai_loading_large_dots_dot-default: 6px;
+$width-ai_loading_large_track-default: 250px;
+$height-ai_loading_large_track-default: 4px;
+$width-ai_loading_large_track_inner-default: 200px;
+$width-ai_loading_colored_icon-default: 16px;
+$height-ai_loading_colored_icon-default: 16px;
+
+// SPACING
+$spacing-ai_loading_small_text-marginLeft: 8px;
+$spacing-ai_loading_large_dots-paddingRight: 1px;
+$spacing-ai_loading_large_track-marginTop: 24px;
+$spacing-ai_loading_large_info-marginTop: 24px;
+$spacing-ai_loading_large_info_desc-marginTop: 8px;
+$spacing-ai_loading_colored-padding: 8px;
+
+// RADIUS
+$radius-ai_loading_small_dots-dot: 50%;
+$radius-ai_loading_large_dots-dot: 50%;
+$radius-ai_loading_large_track-default: 3px;
+$radius-ai_loading_large_track_inner-default: 3px;
+$radius-ai_loading_colored-default: 3px;
+
+// FONT
+$font-ai_loading_default-lineHeight: 20px;
+$font-ai_loading_default-fontSize: 14px;
+$font-ai_loading_small-letterSpacing: -0.14px;
+$font-ai_loading_large-letterSpacing: 0;
+$font-ai_loading_large_info_title-lineHeight: 22px;
+$font-ai_loading_large_info_title-fontSize: 16px;
+$font-ai_loading_large_info_title-fontWeight: 600;
+$font-ai_loading_large_info_desc-lineHeight: 20px;
+$font-ai_loading_large_info_desc-fontSize: 14px;
+$font-ai_loading_large_info_desc-fontWeight: 400;

+ 21 - 0
packages/semi-foundation/floatButton/constants.ts

@@ -0,0 +1,21 @@
+import { BASE_CLASS_PREFIX } from '../base/constants';
+
+const cssClasses = {
+    PREFIX: `${BASE_CLASS_PREFIX}-floatbutton`,
+    ICON_BTN: `${BASE_CLASS_PREFIX}-floatbutton-iconBtn`,
+    ICON_IMG: `${BASE_CLASS_PREFIX}-floatbutton-iconImg`,
+    RECTANGLE: `${BASE_CLASS_PREFIX}-floatbutton-rectangle`,
+    BADGE: `${BASE_CLASS_PREFIX}-floatbutton-badge`,
+    GROUP: `${BASE_CLASS_PREFIX}-floatbutton-group`,
+    GROUP_ITEM: `${BASE_CLASS_PREFIX}-floatbutton-group-item`,
+} as const;
+
+const strings = {
+    TYPE_SET: ['default', 'group'],
+    STATUS_SET: ['normal', 'disabled'],
+    SIZE_SET: ['small', 'medium', 'large'],
+} as const;
+
+const numbers = {} as const;
+
+export { cssClasses, strings, numbers };

+ 137 - 0
packages/semi-foundation/floatButton/floatButton.scss

@@ -0,0 +1,137 @@
+@import './variables.scss';
+
+.semi-floatbutton {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+
+  &-iconBtn {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: $radius-floatbutton_iconBtn;
+    padding: $spacing-floatbutton_iconBtn-paddingTop $spacing-floatbutton_iconBtn-paddingRight $spacing-floatbutton_iconBtn-paddingBottom $spacing-floatbutton_iconBtn-paddingLeft;
+    position: relative;
+    margin: $spacing-floatbutton_iconBtn-marginTop $spacing-floatbutton_iconBtn-marginRight $spacing-floatbutton_iconBtn-marginBottom $spacing-floatbutton_iconBtn-marginLeft;
+    &-small {
+      width: $width-floatbutton_iconBtn-small;
+      height: $height-floatbutton_iconBtn-small;
+    }
+    &-medium {
+      width: $width-floatbutton_iconBtn-medium;
+      height: $height-floatbutton_iconBtn-medium;
+    }
+    &-large {
+      width: $width-floatbutton_iconBtn-large;
+      height: $height-floatbutton_iconBtn-large;
+    }
+    &-default {
+      background: $color-floatbutton_iconBtn-default-bg;
+      background-image: $color-floatbutton_iconBtn-default-bgGradient;
+    }
+    &-disabled {
+      background: $color-floatbutton_iconBtn_disabled-bg;
+    }
+    & + & {
+      margin-left: $spacing-floatbutton_iconBtn-marginLeftNext;
+    }
+  }
+
+  &-iconImg {
+    &-small {
+      width: $width-floatbutton_iconImg-small;
+      height: $height-floatbutton_iconImg-small;
+    }
+    &-medium {
+      width: $width-floatbutton_iconImg-medium;
+      height: $height-floatbutton_iconImg-medium;
+    }
+    &-large {
+      width: $width-floatbutton_iconImg-large;
+      height: $height-floatbutton_iconImg-large;
+    }
+  }
+
+  &-rectangle {
+    position: absolute;
+    flex-shrink: 0;
+    margin-left: $spacing-floatbutton_rectangle-marginLeft;
+    outline-width: $width-floatbutton_rectangle-outline;
+    outline-style: solid;
+    outline-color: $color-floatbutton_rectangle-outline;
+    border-radius: $radius-floatbutton_rectangle;
+    background: $color-floatbutton_rectangle-bg;
+    width: $width-floatbutton_rectangle;
+    height: $height-floatbutton_rectangle;
+    top: $spacing-floatbutton_rectangle-top;
+
+    &-small {
+      left: $spacing-floatbutton_rectangle_small-left;
+      top: $spacing-floatbutton_rectangle_small-top;
+    }
+    &-medium {
+      left: $spacing-floatbutton_rectangle_medium-left;
+    }
+    &-large {
+      left: $spacing-floatbutton_rectangle_large-left;
+    }
+    &-group {
+      left: $spacing-floatbutton_rectangle_group-left;
+      top: $spacing-floatbutton_rectangle_group-top;
+    }
+  }
+
+  &-badge {
+    display: inline-flex;
+    position: absolute;
+    top: $spacing-floatbutton_badge-top;
+    right: $spacing-floatbutton_badge-right;
+    flex-shrink: 0;
+    align-items: center;
+    justify-content: center;
+    outline-width: $width-floatbutton_badge-outline;
+    outline-style: solid;
+    outline-color: $color-floatbutton_badge-outline;
+    border-radius: $radius-floatbutton_badge;
+    background: $color-floatbutton_badge-bg;
+    padding: $spacing-floatbutton_badge-paddingTop $spacing-floatbutton_badge-paddingRight $spacing-floatbutton_badge-paddingBottom $spacing-floatbutton_badge-paddingLeft;
+    font-size: $font-floatbutton_badge-fontSize;
+    color: $color-floatbutton_badge-text;
+    line-height: $font-floatbutton_badge-lineHeight;
+    letter-spacing: $font-floatbutton_badge-letterSpacing;
+  }
+
+  &-group {
+    display: inline-flex;
+    align-items: flex-end;
+    background: $color-floatbutton_group-bg;
+    border-radius: $radius-floatbutton_group;
+    padding: $spacing-floatbutton_group-paddingTop $spacing-floatbutton_group-paddingRight $spacing-floatbutton_group-paddingBottom $spacing-floatbutton_group-paddingLeft;
+    color: $color-floatbutton_group-text;
+    font-size: $font-floatbutton_group-fontSize;
+    .semi-floatbutton-group-item {
+      display: inline-flex;
+      align-items: center;
+      border-radius: $radius-floatbutton_group_item;
+      background: $color-floatbutton_group_item-bg;
+      padding: $spacing-floatbutton_group_item-paddingTop $spacing-floatbutton_group_item-paddingRight $spacing-floatbutton_group_item-paddingBottom $spacing-floatbutton_group_item-paddingLeft;
+      margin-right: $spacing-floatbutton_group_item-marginRight;
+      position: relative;
+      &-text {
+        margin-left: $spacing-floatbutton_group_item_text-marginLeft;
+        min-width: $width-floatbutton_group_item_text-minWidth;
+      }
+    }
+    .semi-floatbutton-rectangle-group {
+      position: absolute;
+      top: $spacing-floatbutton_rectangle_group-top;
+      left: $spacing-floatbutton_rectangle_group-left;
+    }
+    .semi-floatbutton-badge {
+      position: absolute;
+      top: $spacing-floatbutton_badge-top;
+      right: $spacing-floatbutton_badge-right;
+    }
+  }
+}
+

+ 81 - 0
packages/semi-foundation/floatButton/variables.scss

@@ -0,0 +1,81 @@
+// Color
+$color-floatbutton_iconBtn-default-bg: #f6f6fc;
+$color-floatbutton_iconBtn-default-bgGradient: linear-gradient(315deg, #e945ff 0%, #a647ff 30%, #6b61ff 60%, #2e8cff 100%);
+$color-floatbutton_iconBtn_disabled-bg: #f5f5f5; // for var(--semi-color-disabled-bg)
+$color-floatbutton_rectangle-outline: #ffffff; // var(--semi-color-bg-1)
+$color-floatbutton_rectangle-bg: #e45b5b; // var(--semi-color-danger)
+$color-floatbutton_badge-outline: #ffffff; // var(--semi-color-bg-1)
+$color-floatbutton_badge-bg: #e45b5b; // var(--semi-color-danger)
+$color-floatbutton_badge-text: #f6f6fc; // var(--semi-color-bg-2)
+$color-floatbutton_group-bg: #ffffff; // var(--semi-color-bg-0)
+$color-floatbutton_group-text: #1d2129; // var(--semi-color-text-0)
+$color-floatbutton_group_item-bg: #f6f6fc; // rgb(var(--semi-grey-0))
+
+// Width/Height
+$width-floatbutton_iconBtn-small: 12px;
+$height-floatbutton_iconBtn-small: 12px;
+$width-floatbutton_iconBtn-medium: 16px;
+$height-floatbutton_iconBtn-medium: 16px;
+$width-floatbutton_iconBtn-large: 24px;
+$height-floatbutton_iconBtn-large: 24px;
+$width-floatbutton_iconImg-small: 12px;
+$height-floatbutton_iconImg-small: 12px;
+$width-floatbutton_iconImg-medium: 16px;
+$height-floatbutton_iconImg-medium: 16px;
+$width-floatbutton_iconImg-large: 24px;
+$height-floatbutton_iconImg-large: 24px;
+$width-floatbutton_rectangle: 6px;
+$height-floatbutton_rectangle: 6px;
+$width-floatbutton_rectangle-outline: 1px;
+$width-floatbutton_badge-outline: 1px;
+$radius-floatbutton_iconBtn: 30px;
+$radius-floatbutton_rectangle: 9px;
+$radius-floatbutton_badge: 9px;
+$radius-floatbutton_group: 8px;
+$radius-floatbutton_group_item: 4px;
+$width-floatbutton_group_item_text-minWidth: 56px;
+
+// Spacing
+$spacing-floatbutton_iconBtn-paddingTop: 8px;
+$spacing-floatbutton_iconBtn-paddingRight: 8px;
+$spacing-floatbutton_iconBtn-paddingBottom: 8px;
+$spacing-floatbutton_iconBtn-paddingLeft: 8px;
+$spacing-floatbutton_iconBtn-marginTop: 4px;
+$spacing-floatbutton_iconBtn-marginRight: 0px;
+$spacing-floatbutton_iconBtn-marginBottom: 0px;
+$spacing-floatbutton_iconBtn-marginLeft: 0px;
+$spacing-floatbutton_iconBtn-marginLeftNext: 5px; // for & + &
+$spacing-floatbutton_iconImg-paddingTop: 0px;
+$spacing-floatbutton_iconImg-paddingRight: 0px;
+$spacing-floatbutton_iconImg-paddingBottom: 0px;
+$spacing-floatbutton_iconImg-paddingLeft: 0px;
+$spacing-floatbutton_rectangle-marginLeft: 8px;
+$spacing-floatbutton_rectangle-top: 2px;
+$spacing-floatbutton_rectangle_small-left: 15px;
+$spacing-floatbutton_rectangle_small-top: 0px;
+$spacing-floatbutton_rectangle_medium-left: 24px;
+$spacing-floatbutton_rectangle_large-left: 32px;
+$spacing-floatbutton_rectangle_group-left: 100px;
+$spacing-floatbutton_rectangle_group-top: -2px;
+$spacing-floatbutton_badge-top: -6px;
+$spacing-floatbutton_badge-right: -8px;
+$spacing-floatbutton_badge-paddingTop: 0px;
+$spacing-floatbutton_badge-paddingRight: 4px;
+$spacing-floatbutton_badge-paddingBottom: 0px;
+$spacing-floatbutton_badge-paddingLeft: 4px;
+$spacing-floatbutton_group-paddingTop: 6px;
+$spacing-floatbutton_group-paddingRight: 6px;
+$spacing-floatbutton_group-paddingBottom: 6px;
+$spacing-floatbutton_group-paddingLeft: 6px;
+$spacing-floatbutton_group_item-paddingTop: 6px;
+$spacing-floatbutton_group_item-paddingRight: 12px;
+$spacing-floatbutton_group_item-paddingBottom: 6px;
+$spacing-floatbutton_group_item-paddingLeft: 12px;
+$spacing-floatbutton_group_item-marginRight: 4px;
+$spacing-floatbutton_group_item_text-marginLeft: 8px;
+
+// Font
+$font-floatbutton_badge-fontSize: 12px;
+$font-floatbutton_badge-lineHeight: 16px;
+$font-floatbutton_badge-letterSpacing: 0;
+$font-floatbutton_group-fontSize: 14px;

+ 17 - 0
packages/semi-ui/aiCard/_story/aiCard.stories.jsx

@@ -0,0 +1,17 @@
+import React, { useState } from 'react';
+import { AICard } from '../../index';
+
+export default {
+  title: 'AI Card',
+}
+
+
+export const Demo = () => (
+  <div>
+   <AICard type="default" label="AI Summary" icon="https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvbg24f-iwm58xz.svg" children={"hhh"}/>
+   <AICard type="stroked" label="AI Summary" icon="https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvbg24f-iwm58xz.svg" children={"hhh"}/>
+   <AICard type="filled" label="AI Summary" icon="https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvbg24f-iwm58xz.svg" children={"hhh"}/>
+   <AICard type="filledTop" label="AI Summary" icon="https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvbg24f-iwm58xz.svg" children={"hhh"}/>
+  </div>
+);
+

+ 58 - 0
packages/semi-ui/aiCard/index.tsx

@@ -0,0 +1,58 @@
+import React from 'react';
+import cls from 'classnames';
+import { cssClasses } from '@douyinfe/semi-foundation/aiCard/constants';
+import '@douyinfe/semi-foundation/aiCard/aiCard.scss';
+
+const ICON_MAP = {
+    default: 'https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvchagt-4rqbkb6.svg',
+    stroked: 'https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvchagt-cfq9xbz.svg',
+    filled: 'https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvchagt-w7je9be.svg',
+    'filled-top': 'https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvchagt-vut0xqr.svg',
+};
+
+/**
+ * type: 'default' | 'stroked' | 'filled' | 'filled-top'
+ * status: 'normal' | 'hover' | 'active' | 'disabled'
+ */
+function AICardSection({ type = 'default', status = 'normal', title = 'AI Summary', icon, ...props }) {
+    const prefixcls = cssClasses.PREFIX;
+    const blockCls = `${prefixcls}-block`;
+    const typeCls = `${prefixcls}-${type}`;
+
+    // Icon per type
+    const iconUrl = icon || ICON_MAP[type];
+
+    return (
+        <section
+            className={cls(
+                prefixcls,
+                typeCls,
+                `${prefixcls}-status-${status}`
+            )}
+            {...props}
+        >
+            <div className={blockCls}>
+                <div className={`${blockCls}-header`}>
+                    <img className={`${blockCls}-icon`} src={iconUrl} alt="AI Icon" />
+                    <span className={`${blockCls}-title`}>{title}</span>
+                </div>
+                {/* Block content, such as summary, goes here (children) */}
+                <div className={cls(`${blockCls}-footer`)}>
+                    {/* Footer content or separator if needed */}
+                </div>
+            </div>
+            {/* Special decorations for certain types */}
+            {type === 'filled-top' && (
+                <div className={`${prefixcls}-filled-top-bg`} />
+            )}
+            {type === 'filled' && (
+                <div className={`${prefixcls}-separator`} />
+            )}
+            {(type === 'default' || type === 'stroked') && (
+                <div className={`${prefixcls}-rectangle`} />
+            )}
+        </section>
+    );
+}
+
+export default AICardSection;

+ 21 - 0
packages/semi-ui/aiLoading/_story/aiLoading.stories.jsx

@@ -0,0 +1,21 @@
+import React, { useState } from 'react';
+import { AILoading } from '../../index';
+
+export default {
+  title: 'AI Loading',
+}
+
+
+export const Demo = () => (
+  <div>
+    <div>小号尺寸</div>
+    <AILoading />
+    <br />
+    <div>大号尺寸</div>
+    <AILoading type="large" status="processing" />
+    <br />
+    <div>彩色尺寸</div>
+    <AILoading type="colored" status="thinking" />
+  </div>
+);
+

+ 63 - 0
packages/semi-ui/aiLoading/index.tsx

@@ -0,0 +1,63 @@
+import React from 'react';
+import cls from 'classnames';
+import PropTypes from 'prop-types';
+import { cssClasses, strings } from '@douyinfe/semi-foundation/aiLoading/constants';
+import '@douyinfe/semi-foundation/aiLoading/aiLoading.scss';
+
+const prefixcls = cssClasses.PREFIX;
+
+const Loading = ({ type = 'small', title, description, iconUrl, className }) => {
+    if (!strings.TYPE_SET.includes(type)) {
+        // 容错处理,默认用small
+        type = 'small';
+    }
+    return (
+        <div className={cls(prefixcls, className, `${prefixcls}-${type}`)}>
+            {type === 'small' && (
+                <>
+                    <div className={`${prefixcls}-small-dots`}>
+                        <span className={cls(`${prefixcls}-small-dots-dot`, `${prefixcls}-small-dots-dot-1`)} />
+                        <span className={cls(`${prefixcls}-small-dots-dot`, `${prefixcls}-small-dots-dot-2`)} />
+                        <span className={cls(`${prefixcls}-small-dots-dot`, `${prefixcls}-small-dots-dot-3`)} />
+                    </div>
+                    <div className={`${prefixcls}-small-text`}>Thinking...</div>
+                </>
+            )}
+            {type === 'large' && (
+                <React.Fragment>
+                    <div className={`${prefixcls}-large-dots`}>
+                        <span className={cls(`${prefixcls}-large-dots-dot`, `${prefixcls}-large-dots-dot-1`)} />
+                        <span className={cls(`${prefixcls}-large-dots-dot`, `${prefixcls}-large-dots-dot-2`)} />
+                        <span className={cls(`${prefixcls}-large-dots-dot`, `${prefixcls}-large-dots-dot-3`)} />
+                    </div>
+                    <div className={`${prefixcls}-large-track`}>
+                        <div className={`${prefixcls}-large-track-inner`} />
+                    </div>
+                    <div className={`${prefixcls}-large-info`}>
+                        <span className={`${prefixcls}-large-info-title`}>{title || 'In processing...'}</span>
+                        <span className={`${prefixcls}-large-info-desc`}>{description || 'This is the empty description'}</span>
+                    </div>
+                </React.Fragment>
+            )}
+            {type === 'colored' && (
+                <div className={`${prefixcls}-colored-icon`}>
+                    <img
+                        src={iconUrl || 'https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvcemsn-iso1lvx.svg'}
+                        alt={title || 'loading'}
+                        className={cls(`${prefixcls}-colored-icon`)}
+                    />
+                </div>
+            )}
+        </div>
+    );
+};
+
+Loading.propTypes = {
+    type: PropTypes.oneOf(strings.TYPE_SET),
+    title: PropTypes.string,
+    description: PropTypes.string,
+    iconUrl: PropTypes.string,
+    className: PropTypes.string,
+};
+
+export default Loading;

+ 71 - 0
packages/semi-ui/floatButton/_story/floatButton.stories.jsx

@@ -0,0 +1,71 @@
+import React, { useState } from 'react';
+import { FloatButton } from '../../index';
+import { FloatButtonGroup } from '../../floatButton';
+
+export default {
+  title: 'Float Button',
+}
+
+
+export const SizeDemo = () => (
+  <div>
+    <div>sm尺寸</div>
+    <div style={{ display: 'flex', gap: '10px' }}>
+      <FloatButton status="normal" type="default" group={false} size="small" showBadge={true} badgeContent={'new'} />
+      <FloatButton status="normal" type="default" group={false} size="small" showRectangle={true}/>
+      <FloatButton status="normal" type="default" group={false} size="small" />
+    </div>
+    <br />
+    <div>md尺寸</div>
+    <div style={{ display: 'flex', gap: '10px' }}>
+      <FloatButton status="normal" type="default" group={false} size="medium" showBadge={true} badgeContent={'new'} />
+      <FloatButton status="normal" type="default" group={false} size="medium" showRectangle={true}/>
+      <FloatButton status="normal" type="default" group={false} size="medium" />
+    </div>
+
+    <br />
+    <div>lg尺寸</div>
+    <div style={{ display: 'flex', gap: '10px' }}>
+      <FloatButton status="normal" type="default" group={false} size="large" showBadge={true} badgeContent={'new'} />
+      <FloatButton status="normal" type="default" group={false} size="large" showRectangle={true}/>
+      <FloatButton status="normal" type="default" group={false} size="large" />
+    </div>
+
+    <br />
+    <div>disabled尺寸</div>
+    <div style={{ display: 'flex', gap: '10px' }}>
+      <FloatButton type="disabled"  group={false} size="small" showBadge={true} badgeContent={'new'} />
+      <FloatButton type="disabled"  group={false} size="medium" showRectangle={true}/>
+      <FloatButton type="disabled" group={false} size="large" />
+    </div>
+  </div>
+);
+
+export const GroupDemo = () => (
+  <div>
+   <div></div>
+    <div style={{ display: 'flex', gap: '10px' }}>
+      <FloatButton status="normal" type="default" group={true} groupItems={[{
+        icon: 'https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvbquee-l6c0mki.svg',
+        label: 'new',
+        badgeContent: 'new',
+        status: 'normal',
+        size: 'small',
+      }, {
+        icon: 'https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvbquee-l6c0mki.svg',
+        label: 'new',
+        badgeContent: 'new',
+        status: 'normal',
+        size: 'small',
+      },
+      {
+        icon: 'https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvbquee-l6c0mki.svg',
+        label: 'new',
+        badgeContent: 'new',
+        status: 'normal',
+        size: 'small',
+      }]}/>
+    </div>
+  </div>
+);
+

+ 80 - 0
packages/semi-ui/floatButton/index.tsx

@@ -0,0 +1,80 @@
+import React from 'react';
+import cls from 'classnames';
+import { cssClasses, strings } from '@douyinfe/semi-foundation/floatButton/constants';
+import '@douyinfe/semi-foundation/floatButton/floatButton.scss';
+import { IconSearchStroked, IconHelpCircleStroked } from '@douyinfe/semi-icons';
+
+const iconImgs = {
+    default: {
+        small: 'https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvcjc2y-ytad407.svg',
+        medium: 'https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvcjc2y-hfkzeke.svg',
+        large: 'https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvcjc2y-y4y9tsx.svg',
+    },
+    disabled: {
+        small: 'https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvrr4gn-9vdet0m.svg',
+        medium: 'https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvcjc2y-bm6q1vr.svg',
+        large: 'https://cdn-tos-cn.bytedance.net/obj/ies-semi/images/mcvcjc2y-7un8des.svg',
+    },
+};
+
+const badgeContents = {
+    small: '3',
+    large: '99+',
+};
+
+function FloatButton({ type = 'default', status = 'normal', size = 'medium', showRectangle = false, showBadge = false, badgeContent = '', group = false, groupItems = [] }) {
+    const iconCls = cls(cssClasses.ICON_BTN,
+        `${cssClasses.ICON_BTN}-${size}`,
+        `${cssClasses.ICON_BTN}-${type}`,
+        {
+            [`${cssClasses.ICON_BTN}-disabled`]: status === 'disabled',
+        }
+    );
+    const imgCls = cls(cssClasses.ICON_IMG, `${cssClasses.ICON_IMG}-${size}`);
+    // 单枚浮动按钮
+    if (!group) {
+        return (
+            <span className={cssClasses.PREFIX}>
+                <span className={iconCls}>
+                    <img src={iconImgs[type][size]} className={imgCls} alt='' />
+                    {showRectangle ? (
+                        <span className={cls(cssClasses.RECTANGLE, `${cssClasses.RECTANGLE}-${size}`)} />
+                    ) : null}
+                    {showBadge ? (
+                        <span className={cssClasses.BADGE}>{badgeContent}</span>
+                    ) : null}
+                </span>
+            </span>
+        );
+    }
+    // 按钮组
+    return (
+        <span className={cls(cssClasses.PREFIX, cssClasses.GROUP)}>
+            {groupItems.map((item, idx) => {
+                const iconBtnCls = cls(cssClasses.GROUP_ITEM, {
+                    [`${cssClasses.ICON_BTN}-disabled`]: item.status === 'disabled',
+                });
+                return (
+                    <span className={iconBtnCls} key={idx}>
+                        {item.iconType === 'img' ? (
+                            <img src={iconImgs[item.status][item.size]} className={cls(cssClasses.ICON_IMG, `${cssClasses.ICON_IMG}-${item.size}`)} alt='' />
+                        ) : item.iconType === 'search' ? (
+                            <IconSearchStroked className='semi-icons-search' />
+                        ) : (
+                            <IconHelpCircleStroked className='semi-icons-help' />
+                        )}
+                        <span className={`${cssClasses.GROUP_ITEM}-text`}>{item.label}</span>
+                        {item.showRectangle ? (
+                            <span className={cls(cssClasses.RECTANGLE, `${cssClasses.RECTANGLE}-group`)} />
+                        ) : null}
+                        {item.showBadge ? (
+                            <span className={cssClasses.BADGE}>{item.badgeContent}</span>
+                        ) : null}
+                    </span>
+                );
+            })}
+        </span>
+    );
+}
+
+export default FloatButton;

+ 4 - 0
packages/semi-ui/index.ts

@@ -129,3 +129,7 @@ export { default as Cropper } from './cropper';
 export { default as AudioPlayer } from './audioPlayer';
 export { default as UserGuide } from './userGuide';
 export { default as VideoPlayer } from './videoPlayer';
+
+export { default as AILoading } from './aiLoading';
+export { default as AICard } from './aiCard';
+export { default as FloatButton } from './floatButton';