ข้ามไปยังเนื้อหา

สกิน ​

สกิน คือรูปลักษณ์หนึ่งของส่วนประกอบรอบเอดิเตอร์: แถบเครื่องมือ ปุ่มและกลุ่มปุ่มในนั้น bubble menu เมนูดรอปดาวน์ กล่องโต้ตอบ กรอบรอบเนื้อหา และส่วนประกอบเมื่อเลือกรูปภาพ prop skin ใช้เลือกสกิน:

vue
<Tiptapify skin="pastel" />

สกินประกอบด้วยสองส่วน: โทเคน (สีและขนาดในรูปแบบตัวแปร CSS) และ รูปทรง (ตัวแปรเชิงโครงสร้างที่โทเคนไม่สามารถแสดงได้) สกินในตัวทั้งสองคือ default — หน้าตาแบบคลาสสิก แถบเครื่องมือแบบนูนพร้อมกลุ่มปุ่มแบบนูน — และ pastel ซึ่งเป็นหน้าตาแบบสงบ สกินที่กำหนดเองได้รับการปฏิบัติอย่างเท่าเทียม: registerSkin() และออบเจ็กต์สกินแบบอินไลน์ถูกประมวลผลด้วยกลไกเดียวกันทุกประการ และสกินในตัวก็เป็นเพียงสกินที่ลงทะเบียนไว้ ไม่ใช่กรณีพิเศษ

คำศัพท์: สกิน กับ ธีมของ Vuetify ​

  • skin (สกิน) — คำที่ผู้ใช้เห็นสำหรับรูปลักษณ์หนึ่งของส่วนประกอบรอบเอดิเตอร์: โทเค็น + รูปทรง prop คือ skin ไทป์คือ TiptapifySkin* รีจิสทรีคือ registerSkin() และคลาสที่รูทคือ tiptapify-skin-{name}
  • theme (ธีม) — สงวนไว้สำหรับธีมสว่าง/มืดของ Vuetify คอมโพเนนต์ของ Tiptapify ยังคงรับ prop theme จากชื่อธีมปัจจุบันของ Vuetify โดยระบบสกินไม่แตะต้อง

ทั้งสองทำงานร่วมกัน: สีโทเค็นในตัวส่วนใหญ่อ้างอิงตัวแปรธีมของ Vuetify (rgb(var(--v-theme-surface)), …) สกินจึงเปลี่ยนตามโหมดสว่าง/มืดโดยอัตโนมัติ เซลล์สีมืดคงที่ในคอลัมน์ classic — จุดปรับขนาด (rgba(0, 0, 0, .5/.8)) เส้นขอบรูปภาพธรรมดา เงาของ bubble และเงา elevation ของเมนู/กล่องโต้ตอบ — เป็นความตั้งใจ: รูปลักษณ์คลาสสิกใช้ส่วนประกอบสีมืดกลาง ๆ ทั้งในสองธีม และเส้นฐานที่วัดไว้ตรึงค่าเหล่านี้ สกินแบบกำหนดเองอ้างอิงตัวแปรธีมได้อย่างอิสระ — ดูตารางโทเค็น

แนวคิด ​

โทเค็น ​

โทเค็นคือ CSS custom property ที่ชื่อ --tf-* คีย์ในแคตตาล็อกคือ camelCase ของส่วนต่อท้ายของ CSS: toolbarBg → --tf-toolbar-bg, dialogTitleSize → --tf-dialog-title-size ค่าเป็นสตริงธรรมดา — สี shorthand ของเส้นขอบแบบเต็ม เงา ช่องไฟ และรัศมีมุม

กฎของสกินทุกข้อในไลบรารีมีเพียงหนึ่งเดียว โดยอ่านโทเค็นของตนพร้อมค่าสำรองที่เท่ากับค่าคลาสสิก (ค่าฐาน):

css
.tiptapify-toolbar-group {
  border-radius: var(--tf-group-radius, 4px);
}

สกินที่ประมวลผลแล้วจะปล่อยเฉพาะค่าที่แทนที่ออกมาเป็นตัวแปร โดยค่าสำรองใน CSS เป็นผู้ถือค่าฐาน ตัวแปรจะอยู่ที่รูทของเอดิเตอร์ — และเนื่องจากเมนูและกล่องโต้ตอบถูกย้ายออกจากรูท จึงอยู่ที่ wrapper SkinScope ของแต่ละเมนูและที่การ์ดของกล่องโต้ตอบเอง โทเค็นจึงตามไปทุกพื้นผิว

รูปทรง ​

แฟลกหกตัวกำหนดว่าชุดกฎใดถูกใช้ ส่วนโทเค็นเป็นตัวลงสี:

แฟลกค่าสิ่งที่สลับ
toolbarraised · flatVToolbar แบบยกนูนและไม่มีเส้นบางภายใน เทียบกับแถบแบนที่ลงสีอ่อน
groupsbox · flatเซกชันของแถบเครื่องมือเป็นกล่อง VBtnGroup ยกนูน (มาร์กอัปของ 0.3.2: ปุ่มเชื่อมกัน โทเค็นกลุ่มลงสีกล่อง) เทียบกับชุด div แบบ flex ธรรมดา
buttonsvuetify · quietปุ่ม Vuetify ดั้งเดิม เทียบกับปุ่มแบบ ghost ที่มีสถานะกดเป็นสีกลาง
bubblecard · flatคงไว้เพื่อความเข้ากันได้: bubble menu เป็นแถวปุ่มไอคอนที่ลงสีด้วยโทเค็นในทั้งสองรูปทรง (ปุ่มของมันเปลี่ยนตาม buttons)
dialogclassic · softเส้นแบ่งใต้ชื่อเรื่องและปุ่มปิดแบบยกนูน เทียบกับการ์ดนุ่มนวลและปุ่มปิดแบบข้อความ
menuvuetify · softเมนูดรอปดาวน์: รายการของ Vuetify เทียบกับการ์ดสีสว่างที่มีช่องไฟ

รูปทรงที่ประมวลผลแล้วถูกเข้ารหัสไว้บนรูทของเอดิเตอร์เป็นหกคลาส .tiptapify-shape-{flag}-{value} และเปิดเผยเป็น shape: ComputedRef<ResolvedShape> บน useTiptapifyConfig() สำหรับคอมโพเนนต์แถบเครื่องมือแบบกำหนดเอง

Extends ​

สกินถูกประมวลผลทับฐานคลาสสิก จากนั้นตามสาย extends เริ่มจากราก แล้วจึงเป็นสมาชิกของตัวเอง:

classic (base tokens + classic shape) → extends chain → own colors/metrics/flags

ลิงก์ที่ขาดหายจะถูกประมวลผลเป็นสายที่สะสมมา (พร้อมคำเตือนในโหมดพัฒนา) วงวนจะประมวลผลเป็น classic (พร้อมคำเตือนในโหมดพัฒนา) สกินที่ลงทะเบียนไว้อ้างอิงด้วยชื่อ ออบเจกต์สกินแบบอินไลน์ extends ชื่อที่ลงทะเบียนไว้ได้และไม่เข้าสู่รีจิสทรีส่วนกลาง — สกินแบบกำหนดเองจึงไม่รั่วไหลระหว่างเอดิเตอร์ คีย์โทเค็นที่ไม่รู้จักจะถูกข้ามพร้อมคำเตือนในโหมดพัฒนา

เดโมสดของทั้งสามรูปแบบอยู่ที่หน้าตัวอย่างสกิน

แคตตาล็อกโทเค็น ​

ตารางด้านล่างคือสัญญา v1: คีย์ในแคตตาล็อก (TiptapifySkinColors / TiptapifySkinMetrics) คือชื่อที่คุณตั้งค่าได้ เซลล์ classic คือค่าสำรองของ CSS — ค่าที่กฎฐานลงสีเมื่อไม่มีสกินแทนที่โทเค็น

แถบเครื่องมือ / แถบ ​

โทเค็นตัวแปร CSSclassicpastel
toolbarBg--tf-toolbar-bgrgb(var(--v-theme-surface))rgba(var(--v-theme-on-surface), 0.03)
toolbarBorderBottom--tf-toolbar-border-bottomnone1px solid rgba(var(--v-border-color), var(--v-border-opacity))
toolbarFg--tf-toolbar-fginheritrgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity))

รายการ / กลุ่ม / เส้นแบ่ง ​

โทเค็นตัวแปร CSSclassicpastel
itemsPadding--tf-items-padding12px 16px6px 8px
itemsGap--tf-items-gapnormal ¹6px
itemsRowGap--tf-items-row-gap5px4px
groupGap--tf-group-gap0px2px
groupHeight--tf-group-height32pxauto
groupBg--tf-group-bgrgb(var(--v-theme-surface))transparent
groupRadius--tf-group-radius4px0px
groupShadow--tf-group-shadowVuetify elevation 2 ²none
dividerWidth--tf-divider-width0px (ตัวเว้นระยะ: margin 0 4px)1px
dividerHeight--tf-divider-height0px20px
dividerColor--tf-divider-colortransparentrgba(var(--v-border-color), var(--v-border-opacity))

¹ ค่า classic ที่วัดได้คือ normal — ค่า flex ดั้งเดิมของ Vuetify ซึ่งเป็นสิ่งที่ค่าสำรองของ CSS ถือไว้ ส่วนค่าฐานในแคตตาล็อก 0px คือความยาวที่ระบุชัดเจนซึ่งเทียบเท่า สำหรับใช้แทนที่ในสกิน

² เซลล์ที่เขียนว่า "Vuetify elevation n" เป็นเพียงคำอธิบาย: สตริงเงาสามชั้นที่แน่นอนคือค่าที่วัดได้ในไฟล์ฐานที่คอมมิตไว้ (src/skins/__fixtures__/skin-baseline.json) และเป็นค่าสำรองของ CSS สำหรับ groupShadow นั่นคือ elevation 2 (0 3px 1px -2px …, 0 2px 2px 0 …, 0 1px 5px 0 …) — ภายใต้ groups: 'box' เซกชันคือ VBtnGroup (elevation="4") และกฎของโทเค็นลงสีกล่องด้วยเงาสามชั้นนี้ทับ elevation ของกลุ่มเอง: กล่องเป็นเจ้าของ elevation ส่วนปุ่มลูกที่เชื่อมกันไม่มี

ปุ่ม ​

โทเค็นเหล่านี้ถูกใช้เฉพาะภายใต้ buttons: 'quiet' — ดูความเข้าถึงได้

โทเค็นตัวแปร CSSค่าแบบ quiet (classic: Vuetify ดั้งเดิม)
buttonFg--tf-button-fgrgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity))
buttonHoverBg--tf-button-hover-bgrgba(var(--v-theme-on-surface), 0.07)
buttonHoverFg--tf-button-hover-fgrgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity))
buttonActiveBg--tf-button-active-bgrgba(var(--v-theme-on-surface), 0.1)
buttonActiveHoverBg--tf-button-active-hover-bgrgba(var(--v-theme-on-surface), 0.14)
buttonRadius--tf-button-radius6px

Bubble menu (การเลือก บรรทัดว่าง รูปภาพ) ​

โทเค็นตัวแปร CSSclassicpastel
bubbleBg--tf-bubble-bgrgb(var(--v-theme-surface))เหมือนกัน
bubbleBorder--tf-bubble-bordernone1px solid rgba(var(--v-border-color), var(--v-border-opacity))
bubbleShadow--tf-bubble-shadow0 4px 14px rgba(0, 0, 0, 0.12), 0 1px 3px rgba(0, 0, 0, 0.08)0 6px 20px rgba(0, 0, 0, 0.12)
bubbleRadius--tf-bubble-radius6px10px
bubblePadding--tf-bubble-padding4pxเหมือนกัน
bubbleGap--tf-bubble-gap2pxเหมือนกัน
โทเค็นตัวแปร CSSclassicpastel
menuListPadding--tf-menu-list-padding8px 0px4px
menuRadius--tf-menu-radius4px8px
menuBorder--tf-menu-bordernone1px solid rgba(var(--v-border-color), var(--v-border-opacity))
menuShadow--tf-menu-shadowVuetify elevation 8 ²0 4px 16px rgba(0, 0, 0, 0.08)
menuItemRadius--tf-menu-item-radius0px6px
menuItemPadding--tf-menu-item-paddingVuetify ³4px 8px
menuItemMinHeight--tf-menu-item-min-heightVuetify ³34px
menuItemActiveBg--tf-menu-item-active-bgVuetify ³rgba(var(--v-theme-on-surface), 0.06)

³ กล่องรายการ (รัศมีมุม เงา ช่องไฟของรายการ) ของเมนูคลาสสิกปัจจุบันเป็นกฎของสกิน — wrapper โทเค็น SkinScope อยู่ระหว่างกฎลูกของ Vuetify เองกับรายการ ไลบรารีจึงคืนพิกเซลเหล่านั้นเป็นกฎของสกินที่อ่านโทเค็นข้างต้น พิกเซลของไอเทมยังเป็นของ Vuetify ดั้งเดิม (ไฟล์ฐานวัดค่าเริ่มต้นของ Vuetify ไว้ตรงนั้น): โทเค็นไอเทมทั้งสี่ไม่มีผลขณะ menu: 'vuetify'

กล่องโต้ตอบ ​

โทเค็นตัวแปร CSSclassicpastel
dialogShadow--tf-dialog-shadowVCard elevation ²0 20px 48px rgba(0, 0, 0, 0.16), 0 2px 6px rgba(0, 0, 0, 0.06)
dialogRadius--tf-dialog-radius4px (VCard)12px
dialogHeaderPadding--tf-dialog-header-padding8px 16px16px 12px 12px 20px
dialogContentPadding--tf-dialog-content-padding16px 24px 24px4px 20px
dialogActionsPadding--tf-dialog-actions-padding8px16px 20px 20px
dialogTitleSize--tf-dialog-title-size1.25rem1.125rem
dialogTitleWeight--tf-dialog-title-weight400600
dialogFieldRadius--tf-dialog-field-radiusค่าเริ่มต้นของฟิลด์ (4px)8px (outlined)
dialogActionBtnMinHeight--tf-dialog-action-btn-min-heightVuetify (auto)38px
dialogActionBtnRadius--tf-dialog-action-btn-radiusVuetify (4px)8px
dialogGridGap--tf-dialog-grid-gap24px16px

กรอบ (ตัวห่อเส้นขอบของเอดิเตอร์) ​

โทเค็นตัวแปร CSSclassicpastel
frameBorder--tf-frame-border1px solid rgba(var(--v-border-color), var(--v-border-opacity)), ไม่มีขอบบนขอบเต็ม
frameBg--tf-frame-bgtransparentrgb(var(--v-theme-surface))
frameShadow--tf-frame-shadownone0 1px 2px rgba(0, 0, 0, 0.05)

ภายใต้รูปทรงแถบเครื่องมือแบบแบน กรอบยังลงสีส่วนต่างรายด้าน (ขอบบน และขอบล่างที่ความทึบของเส้นขอบ 1.6 เท่า) ส่วนต่างนั้นเป็นของรูปทรง ไม่ใช่ของโทเค็น: โทเค็นเข้าถึงไม่ได้

รูปภาพและจุดปรับขนาด ​

โทเค็นตัวแปร CSSclassicpastel
imageRadius--tf-image-radius0.125rem4px
imageBg--tf-image-bgtransparentrgba(var(--v-theme-on-surface), 0.04)
imageOutline--tf-image-outline1px solid rgba(0, 0, 0, 0.25) (เมื่อเลือก)2px solid rgb(var(--v-theme-primary))
imageOutlineHover--tf-image-outline-hovertransparentrgba(var(--v-theme-primary), 0.35)
handleBg--tf-handle-bgrgba(0, 0, 0, 0.5)rgb(var(--v-theme-primary))
handleBgHover--tf-handle-bg-hoverrgba(0, 0, 0, 0.8) (เมื่อวางเมาส์)rgb(var(--v-theme-primary))
handleBorder--tf-handle-bordernone2px solid rgb(var(--v-theme-surface))
handleShadow--tf-handle-shadownone0 0 0 1px rgba(0, 0, 0, 0.15)
handleRadius--tf-handle-radius2px50%

แถบเครื่องมือของรูปภาพทำตามแฟลก buttons: ภายใต้รูปทรง quiet จะได้พื้นผิวแบบ quiet — ระยะห่าง 2px/4px อ่าน --tf-bubble-gap / --tf-bubble-padding พร้อมค่าสำรองของเมนูรูปภาพ ไม่มีโทเค็นเฉพาะสำหรับแถบเครื่องมือรูปภาพ

ไม่อยู่ในแคตตาล็อก (ขอบเขตของทางออกฉุกเฉิน) ​

มิติบางอย่างที่กล่าวถึงในภาพรวมการออกแบบไม่มีโทเค็นในแคตตาล็อกของ v1: ความสูงแถบเครื่องมือ ความกว้างกรอบ รัศมีมุมกรอบ ความกว้างปุ่ม ช่องไฟของปุ่ม ความกว้างกล่องโต้ตอบ ตารางแคตตาล็อกข้างต้นคือสัญญา สำหรับพิกเซลเหล่านี้ให้เปิดทางออกฉุกเฉินและจัดสไตล์คลาสที่คงที่โดยตรง

ความเข้าถึงได้ ​

สัญญาที่ระบุไว้ครั้งเดียวและทุกกลุ่มข้างต้นปฏิบัติตาม:

โทเค็นลงสีพื้นผิวก็ต่อเมื่อรูปทรงเปิดใช้พื้นผิวนั้น ส่วนภาพดั้งเดิมของ Vuetify จัดสไตล์ผ่านสีธีมของ Vuetify

แยกตามกลุ่ม:

  • แถบเครื่องมือ กรอบ ส่วนประกอบรูปภาพ/จุดปรับขนาด — ใช้งานในทุกรูปทรง โทเค็นลงสีให้ และเซลล์ classic คือรูปลักษณ์ดั้งเดิมที่โทเค็นถอยกลับไปใช้
  • กล่องของกลุ่ม (groupBg, groupRadius, groupHeight, groupShadow) — ภายใต้ groups: 'box' เซกชันคือ VBtnGroup (โครงสร้างของ 0.3.2: ปุ่มเชื่อมกัน กล่องถือ elevation) กฎของกล่องลงสีด้วยโทเค็นของกลุ่ม และ --tf-group-height รักษาสัญญา 32px ด้วย !important (กฎ density ของ Vuetify ต่อสู้กับมัน เหมือนใน 0.3.2) ภายใต้ groups: 'flat' เซกชันเป็นชุด div ธรรมดา (โปร่งใส ไม่มีเงา รัศมีมุม 0 คือค่าฐานของรูปทรง)
  • เส้นแบ่งบาง (dividerWidth/Height/Color) — เส้นบางที่มองเห็นได้เป็นฟีเจอร์ของ groups: 'flat' ในรูปทรงกล่อง เส้นแบ่งเป็นตัวเว้นระยะขนาดศูนย์ (margin: 0 4px จากกฎฐาน)
  • ช่องไฟ/ระยะห่างของรายการ — ชุด 6px 8px แบบกระชับถูกจำกัดไว้กับแถบแบน (toolbar: 'flat') ส่วนระยะห่างของกลุ่มจำกัดไว้กับเซกชันแบน (groups: 'flat') แถบยกนูนคงเมตริกคลาสสิกไว้
  • ปุ่ม (buttonFg, buttonHover*, buttonActive*, buttonRadius) — ไม่มีผลภายใต้ buttons: 'vuetify': ปุ่ม Vuetify ดั้งเดิมลงสีสถานะของตัวเอง จัดสไตล์ด้วยสีธีมของ Vuetify (primary, surface, …) — รูปทรงคลาสสิกสืบทอดสีเหล่านั้นโดยเจตนา
  • เมตริกของไอเทมเมนู (menuItemRadius/Padding/MinHeight/ActiveBg) — ไม่มีผลภายใต้ menu: 'vuetify' Vuetify เป็นเจ้าของพิกเซลของไอเทมเหล่านั้น กล่องรายการของเมนู (รัศมีมุม/เงา/ช่องไฟ) สกินลงสีในทั้งสองรูปทรง (ดูหมายเหตุเมนู)
  • ส่วนประกอบแบบนุ่มนวลของกล่องโต้ตอบ (dialogActionBtn*, dialogFieldRadius, ช่องไฟแบบนุ่มนวล เส้นแบ่งที่หายไป) — ลงสีภายใต้ dialog: 'soft' ภายใต้ dialog: 'classic' กล่องโต้ตอบคือ VCard พร้อมช่องไฟแบบคลาสสิก
  • ส่วนประกอบของ Bubble — เมนูการเลือก บรรทัดว่าง และรูปภาพเป็นแถวปุ่มไอคอนแถวเดียวในทั้งสองรูปทรง ลงสีด้วยโทเค็นของ bubble bubble ไม่เปลี่ยนมาร์กอัปของมันอีกต่อไป

ค่าที่แทนที่ซึ่งเท่ากับค่าฐานในแคตตาล็อกจะไม่ถูกปล่อยออกมา — ภายใต้รูปทรงที่ไม่ใช่คลาสสิก ค่าฐานของรูปทรงเองจะลงสีผ่านค่าสำรองของ CSS ดังนั้นการ "คืน" ค่าคลาสสิก (เช่นตั้ง buttonActiveBg กลับเป็น rgb(var(--v-theme-primary)) ภายใต้ buttons: 'quiet') จึงไม่เกิดผลใด ๆ อย่างเงียบ ๆ หากต้องการบังคับค่าที่ดูเหมือนคลาสสิกภายใต้รูปทรงที่ไม่ใช่คลาสสิก ให้ตั้งค่าที่แทนที่ซึ่งต่างจากค่าฐานในแคตตาล็อก — ค่าลิเทอรัลที่เทียบเท่า เช่น rgba(var(--v-theme-primary), 1) ลงสีเหมือนกันทุกประการและไม่ถูกข้าม

โทเค็นไม่ได้ถูกเชื่อมเข้ากับเส้นทางดั้งเดิมโดยเจตนา — นั่นคือสิ่งที่ทำให้ default เหมือนรูปลักษณ์คลาสสิกทุกพิกเซลในขณะที่ทุกอย่างผ่านแคตตาล็อก

สูตรการปรับแต่ง ​

ขยาย pastel ​

สืบทอดรูปทรง quiet และลงสีใหม่ในบางพื้นผิว ชื่อที่ลงทะเบียนไว้ใช้ได้กับทุกเอดิเตอร์:

ts
// main.ts — call once, before any editor mounts
import { registerSkin } from 'tiptapify'

registerSkin('mint', {
  extends: 'pastel',
  colors: {
    toolbarBg: 'rgba(0, 128, 0, 0.05)',   // mint tint over the pastel wash
    handleBg: 'rgb(0, 100, 0)',           // deep green handles
    handleBgHover: 'rgb(0, 128, 0)',
    imageOutline: '2px solid rgb(0, 100, 0)',
    imageOutlineHover: 'rgba(0, 100, 0, 0.35)',
  },
})
vue
<Tiptapify skin="mint" />

รูปทรง (flat/quiet/soft) มาจาก pastel โทเค็นที่ไม่ได้แตะต้องคงค่าของ pastel ไว้ — พื้นสีของปุ่ม quiet ยังเป็นสีกลาง เฉพาะสิ่งที่คุณแทนที่เท่านั้นที่เปลี่ยน นี่คือสกินที่เรนเดอร์สดอยู่บนหน้าตัวอย่าง

ขยาย default ​

คงโครงสร้างคลาสสิกไว้ ปรับแต่งสี:

ts
registerSkin('paper', {
  extends: 'default',
  colors: { toolbarBg: 'rgb(var(--v-theme-background))' },
  metrics: { groupRadius: '8px', itemsPadding: '10px 14px' },
})

extends: 'default' คือรากโดยปริยาย จึงละคีย์ได้: { toolbar: 'flat', … } ก็เริ่มจากคลาสสิกเช่นกัน

กำหนดเองทั้งหมด ​

ไม่มี extends ไม่ต้องลงทะเบียน: ส่งออบเจกต์ให้ prop skin แล้วตั้งแฟลกรูปทรงและโทเค็นได้อย่างอิสระ name ใช้ใส่ป้ายของคุณเองบนคลาสที่รูท (ดูด้านล่าง) หากไม่มีจะเป็น tiptapify-skin-inline

vue
<script setup lang="ts">
import { defineSkin } from 'tiptapify'

const slate = defineSkin({
  name: 'slate',
  toolbar: 'flat',
  groups: 'flat',
  buttons: 'quiet',
  bubble: 'flat',
  dialog: 'soft',
  menu: 'soft',
  colors: { toolbarBg: 'rgb(30, 41, 59)', toolbarFg: 'rgb(226, 232, 240)' },
  metrics: { buttonRadius: '8px' },
})
</script>

<template>
  <Tiptapify :skin="slate" />
</template>

defineSkin เป็นฟังก์ชันช่วยแบบ identity สำหรับนิยามค่าคงที่ที่มีไทป์ (ไม่เข้าสู่รีจิสทรีใด ๆ) แฟลกรูปทรงตั้งทีละตัวได้ — แฟลกที่คุณละไว้ยังเป็น classic

ทางออกฉุกเฉิน: คลาสที่รูท ​

รูทของเอดิเตอร์ทุกตัวมี tiptapify-skin-{name} (tiptapify-skin-inline สำหรับออบเจกต์อินไลน์ที่ไม่มีชื่อ) ไลบรารีไม่เคยผูกกฎใด ๆ กับชื่อสกิน — คลาสนี้เป็นของคุณ:

css
/* Style the frame of one skin, dimensions the catalog does not cover */
.tiptapify-skin-mint .tiptapify-frame {
  max-width: 720px;
  margin-inline: auto;
}

จุดเกาะที่คงที่สำหรับเขียนสไตล์:

คลาสอยู่ที่
tiptapify-skin-{name}รูทของเอดิเตอร์
tiptapify-shape-{flag}-{value} ×6รูทของเอดิเตอร์ — รูปทรงที่ประมวลผลแล้ว
tiptapify-toolbar · tiptapify-toolbar-items · tiptapify-toolbar-group · menu-dividerแถบเครื่องมือและเซกชันของมัน
tiptapify-quiet-buttonsรูทของแถบเครื่องมือและ bubble ภายใต้ buttons: 'quiet'
tiptapify-bubble-row · tiptapify-bubble-dividerแถวของ bubble menu ทุกตัวและเส้นบางระหว่างกลุ่ม
tiptapify-bubble-menu · floating-menu · tiptapify-image-menuแถวของเมนูการเลือก บรรทัดว่าง และรูปภาพ
tiptapify-btn--activeปุ่มที่ถูกกดของ bubble menu (มาร์กที่ใช้งานอยู่ การลอยของรูปภาพ)
tiptapify-menu · tiptapify-menu--softเนื้อหา overlay ของดรอปดาวน์ ตัวพากฎของเมนูแบบนุ่มนวล
tiptapify-skin-scopediv ขอบเขตโทเค็นภายในเมนูที่ถูกย้ายออก
tiptapify-dialog · tiptapify-dialog--softการ์ดของกล่องโต้ตอบและตัวพาแบบนุ่มนวล
tiptapify-frameตัวห่อเส้นขอบของเอดิเตอร์

การป้องกันธีมของผู้ใช้ เลเยอร์สกินสร้างขึ้นให้อยู่รอดภายใต้ธีมแอดมินที่เพิ่มช่องไฟและลงสีทับส่วนภายในของ Vuetify: กฎถูกจำกัดด้วยคลาสของรูปทรง/ตัวพา ใช้คลาสซ้ำสองชั้น (.v-list.v-list, .v-btn.v-btn.v-btn) เพื่อเพิ่ม specificity และคง !important ไว้เฉพาะที่กรณีธีมแอดมินของคอมมิตฐานพิสูจน์ว่าจำเป็น (ชุดป้องกันใน menu.css) ข้อตกลงที่ช่วยให้การแทนที่ของคุณเองใช้งานได้ในสนามเดียวกัน:

  • จำกัดขอบเขต CSS ของคุณภายใต้ .tiptapify-skin-{name} (หรือคลาสของรูปทรง) — ไม่ใช่บนส่วนภายในเปล่า ๆ ของ Vuetify
  • ควรใช้โทเค็น (--tf-*) สำหรับมิติในแคตตาล็อก และใช้คลาสสำหรับส่วนที่เหลือ
  • ใช้การซ้ำคลาสให้ตรงกันเมื่อแทนที่คอมโพเนนต์ของ Vuetify (.v-list-item เดี่ยว ๆ จะแพ้กฎของสกิน)

ข้อตกลงด้านภาพ (หมายเหตุสำหรับผู้ร่วมพัฒนา) ​

สไตล์ที่คำนวณแล้วของสกินในตัวถูกตรึงไว้ด้วยไฟล์ฐาน src/skins/__fixtures__/skin-baseline.json (13 เซกชัน × สว่าง/มืด): เลเยอร์ CSS เสร็จสมบูรณ์เมื่อเมทริกซ์ที่วัดได้ตรงกับไฟล์นั้น หมายเหตุสำหรับการอ่านไฟล์ฐาน:

  • มิติของ hover/active ไม่สามารถบังคับจากหน้าได้ การบันทึกจึงอ่านข้อความประกาศของกฎ CSSOM ที่พบเป็นอันดับแรกสำหรับแต่ละตัวเลือก hover และประมวลผลผ่านอิลิเมนต์ probe ภายในรูทของสกิน (ฟิลด์ resolved) — นี่คือสัญญาของกฎที่ชนะ ไม่ใช่ภาพสแนปช็อต :hover สด
  • _meta.selectors.menu บันทึกข้อความตัวเลือกก่อนมี SkinScope ไฟล์ฐานถูกตรึง (ค่ามาตรฐาน) ฟิลด์นี้จึงล้าสมัยโดยตั้งใจ ชุดบันทึกปัจจุบันตรึงตัวเลือกปัจจุบัน
  • ไฟล์ฐานเก็บการเปลี่ยนแปลงที่ได้รับอนุญาตไว้ใน _meta.notes: การคืนมาร์กอัป VBtnGroup ภายใต้ groups: 'box' เมื่อวันที่ 2026-10-18 ได้วัดฟิลด์ปุ่มลูก groupBtn/buttonsActive ของ classic ใหม่ (มุมที่เชื่อมกัน กล่องเป็นเจ้าของ elevation) ฟิลด์ของ pastel ไม่ถูกแตะ — การเปลี่ยนภาพโดยเจตนาจะอัปเดตเฉพาะเซลล์ classic ที่ได้รับผลกระทบ บันทึกหมายเหตุ และส่งพร้อมบรรทัดใน CHANGELOG

ดูเพิ่มเติม ​

เผยแพร่ภายใต้สัญญาอนุญาต MIT