@korioinc/next-core 2.0.48 → 2.0.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -53,5 +53,5 @@ export default function LocaleSwitcher({ languages } = {}) {
53
53
  if (!currentLanguage) {
54
54
  return null;
55
55
  }
56
- return (_jsxs(Menu, { as: 'div', className: 'relative', children: [_jsx(MenuButton, { className: 'glass-border-subtle bg-glass-surface hover:bg-glass-surface-interactive relative inline-flex h-9 w-9 items-center justify-center rounded-md border transition-colors', children: currentLanguage.flag }), _jsx(Transition, { as: Fragment, enter: 'transition ease-out duration-100', enterFrom: 'transform opacity-0 scale-95', enterTo: 'transform opacity-100 scale-100', leave: 'transition ease-in duration-75', leaveFrom: 'transform opacity-100 scale-100', leaveTo: 'transform opacity-0 scale-95', children: _jsx(MenuItems, { anchor: 'bottom end', className: 'glass glass-surface-subtle glass-backdrop-sm glass-shadow-sm glass-border-strong z-100 w-48 rounded-md border ring-1 ring-black/5 [--anchor-gap:8px] focus:outline-none', children: _jsx("div", { className: 'py-1', children: availableLanguages.map((language) => (_jsx(MenuItem, { children: _jsxs("button", { onClick: () => changeLanguage(language.code), className: 'data-[focus]:bg-glass-surface-interactive text-foreground group flex w-full items-center gap-2 px-3 py-2 text-sm transition-colors', children: [language.flag, _jsx("span", { className: 'whitespace-nowrap', children: language.name }), currentLocale === language.code && (_jsx("svg", { className: 'ml-auto h-4 w-4', fill: 'none', stroke: 'currentColor', viewBox: '0 0 24 24', children: _jsx("path", { strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: 2, d: 'M5 13l4 4L19 7' }) }))] }) }, language.code))) }) }) })] }));
56
+ return (_jsxs(Menu, { as: 'div', className: 'relative', children: [_jsx(MenuButton, { className: 'glass glass-border-subtle hover:bg-glass-interactive relative inline-flex h-9 w-9 items-center justify-center rounded-md border transition-colors', children: currentLanguage.flag }), _jsx(Transition, { as: Fragment, enter: 'transition ease-out duration-100', enterFrom: 'transform opacity-0 scale-95', enterTo: 'transform opacity-100 scale-100', leave: 'transition ease-in duration-75', leaveFrom: 'transform opacity-100 scale-100', leaveTo: 'transform opacity-0 scale-95', children: _jsx(MenuItems, { anchor: 'bottom end', className: 'glass-subtle glass-backdrop-sm glass-shadow-sm glass-border-strong z-100 w-48 rounded-md border ring-1 ring-black/5 [--anchor-gap:8px] focus:outline-none', children: _jsx("div", { className: 'py-1', children: availableLanguages.map((language) => (_jsx(MenuItem, { children: _jsxs("button", { onClick: () => changeLanguage(language.code), className: 'data-[focus]:bg-glass-interactive text-foreground group flex w-full items-center gap-2 px-3 py-2 text-sm transition-colors', children: [language.flag, _jsx("span", { className: 'whitespace-nowrap', children: language.name }), currentLocale === language.code && (_jsx("svg", { className: 'ml-auto h-4 w-4', fill: 'none', stroke: 'currentColor', viewBox: '0 0 24 24', children: _jsx("path", { strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: 2, d: 'M5 13l4 4L19 7' }) }))] }) }, language.code))) }) }) })] }));
57
57
  }
@@ -38,8 +38,8 @@ const ThemeSwitcher = () => {
38
38
  setTheme(nextTheme);
39
39
  };
40
40
  if (!mounted) {
41
- return (_jsx("button", { className: 'glass-border-subtle bg-glass-surface relative inline-flex h-9 w-9 items-center justify-center rounded-md border opacity-0', "aria-hidden": 'true', children: _jsx("div", { className: 'h-5 w-5' }) }));
41
+ return (_jsx("button", { className: 'glass glass-border-subtle relative inline-flex h-9 w-9 items-center justify-center rounded-md border opacity-0', "aria-hidden": 'true', children: _jsx("div", { className: 'h-5 w-5' }) }));
42
42
  }
43
- return (_jsxs("button", { onClick: toggleTheme, className: `glass-border-subtle bg-glass-surface hover:bg-glass-surface-interactive relative inline-flex h-9 w-9 items-center justify-center rounded-md border ${canAnimateColors ? 'transition-colors' : ''}`, "aria-label": `Switch theme (current: ${currentThemeLabel})`, title: `Theme: ${currentThemeLabel} (click to change)`, children: [_jsxs("svg", { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: `absolute h-5 w-5 transition-all ${currentTheme === 'light' ? 'scale-100 rotate-0 opacity-100' : 'scale-0 rotate-90 opacity-0'}`, children: [_jsx("circle", { cx: '12', cy: '12', r: '5' }), _jsx("line", { x1: '12', y1: '1', x2: '12', y2: '3' }), _jsx("line", { x1: '12', y1: '21', x2: '12', y2: '23' }), _jsx("line", { x1: '4.22', y1: '4.22', x2: '5.64', y2: '5.64' }), _jsx("line", { x1: '18.36', y1: '18.36', x2: '19.78', y2: '19.78' }), _jsx("line", { x1: '1', y1: '12', x2: '3', y2: '12' }), _jsx("line", { x1: '21', y1: '12', x2: '23', y2: '12' }), _jsx("line", { x1: '4.22', y1: '19.78', x2: '5.64', y2: '18.36' }), _jsx("line", { x1: '18.36', y1: '5.64', x2: '19.78', y2: '4.22' })] }), _jsx("svg", { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: `absolute h-5 w-5 transition-all ${currentTheme === 'dark' ? 'scale-100 rotate-0 opacity-100' : 'scale-0 -rotate-90 opacity-0'}`, children: _jsx("path", { d: 'M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z' }) }), _jsxs("svg", { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: `absolute h-5 w-5 transition-all ${currentTheme === 'system' ? 'scale-100 rotate-0 opacity-100' : 'scale-0 rotate-90 opacity-0'}`, children: [_jsx("rect", { x: '3', y: '4', width: '18', height: '12', rx: '2' }), _jsx("line", { x1: '8', y1: '20', x2: '16', y2: '20' }), _jsx("line", { x1: '12', y1: '16', x2: '12', y2: '20' })] })] }));
43
+ return (_jsxs("button", { onClick: toggleTheme, className: `glass glass-border-subtle hover:bg-glass-interactive relative inline-flex h-9 w-9 items-center justify-center rounded-md border ${canAnimateColors ? 'transition-colors' : ''}`, "aria-label": `Switch theme (current: ${currentThemeLabel})`, title: `Theme: ${currentThemeLabel} (click to change)`, children: [_jsxs("svg", { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: `absolute h-5 w-5 transition-all ${currentTheme === 'light' ? 'scale-100 rotate-0 opacity-100' : 'scale-0 rotate-90 opacity-0'}`, children: [_jsx("circle", { cx: '12', cy: '12', r: '5' }), _jsx("line", { x1: '12', y1: '1', x2: '12', y2: '3' }), _jsx("line", { x1: '12', y1: '21', x2: '12', y2: '23' }), _jsx("line", { x1: '4.22', y1: '4.22', x2: '5.64', y2: '5.64' }), _jsx("line", { x1: '18.36', y1: '18.36', x2: '19.78', y2: '19.78' }), _jsx("line", { x1: '1', y1: '12', x2: '3', y2: '12' }), _jsx("line", { x1: '21', y1: '12', x2: '23', y2: '12' }), _jsx("line", { x1: '4.22', y1: '19.78', x2: '5.64', y2: '18.36' }), _jsx("line", { x1: '18.36', y1: '5.64', x2: '19.78', y2: '4.22' })] }), _jsx("svg", { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: `absolute h-5 w-5 transition-all ${currentTheme === 'dark' ? 'scale-100 rotate-0 opacity-100' : 'scale-0 -rotate-90 opacity-0'}`, children: _jsx("path", { d: 'M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z' }) }), _jsxs("svg", { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: `absolute h-5 w-5 transition-all ${currentTheme === 'system' ? 'scale-100 rotate-0 opacity-100' : 'scale-0 rotate-90 opacity-0'}`, children: [_jsx("rect", { x: '3', y: '4', width: '18', height: '12', rx: '2' }), _jsx("line", { x1: '8', y1: '20', x2: '16', y2: '20' }), _jsx("line", { x1: '12', y1: '16', x2: '12', y2: '20' })] })] }));
44
44
  };
45
45
  export default ThemeSwitcher;
@@ -21,5 +21,5 @@ export default function Tooltip({ children, content }) {
21
21
  });
22
22
  const hover = useHover(context);
23
23
  const { getReferenceProps, getFloatingProps } = useInteractions([hover]);
24
- return (_jsxs("div", { ref: refs.setReference, ...getReferenceProps(), className: 'inline-block', children: [children, isOpen && (_jsx(FloatingPortal, { children: _jsx("div", { ref: refs.setFloating, style: floatingStyles, className: 'glass glass-surface-strong glass-texture-subtle glass-border-strong glass-backdrop-lg glass-shadow-lg text-foreground z-100 rounded-lg px-3 py-2 text-sm font-medium', ...getFloatingProps(), children: content }) }))] }));
24
+ return (_jsxs("div", { ref: refs.setReference, ...getReferenceProps(), className: 'inline-block', children: [children, isOpen && (_jsx(FloatingPortal, { children: _jsx("div", { ref: refs.setFloating, style: floatingStyles, className: 'glass-strong glass-texture-subtle glass-border-strong glass-backdrop-lg glass-shadow-lg text-foreground z-100 rounded-lg px-3 py-2 text-sm font-medium', ...getFloatingProps(), children: content }) }))] }));
25
25
  }
@@ -1,59 +1,58 @@
1
1
  # Glass Token 기본 컴포넌트 가이드
2
2
 
3
- 이 디렉터리의 `globals.css`는 패키지 소비 프로젝트에서도 적용되는 glass UI
4
- 토큰의 원본입니다. 컴포넌트 className을 작성할 때는 여기 정의된 glass token
5
- family를 조합하고, 소비 프로젝트에서 임의 glass 스타일을 새로 만들지
6
- 않습니다.
3
+ 이 디렉터리의 `globals.css`는 패키지 소비 프로젝트에도 적용되는 glass UI 토큰의 원본입니다.
4
+ 컴포넌트 className을 작성할 때는 여기 정의된 glass token family를 조합하고, 소비 프로젝트에서 임의 glass 스타일을 새로 만들지 않습니다.
7
5
 
8
6
  ## 목표
9
7
 
10
8
  - 기본 컴포넌트가 light/dark 모드에서 같은 역할과 밀도를 갖게 만든다.
11
- - 화면 영역이 과하게 하얗게 뜨지 않도록 넓은 표면에는 낮은 surface를 쓴다.
12
- - `rgba`, 임의 `backdrop-blur`, 임의 shadow, arbitrary `[box-shadow]` 대신
13
- glass token class를 조합한다.
9
+ - 가장 자주 쓰는 기본 glass 표면은 짧게 `glass`로 쓴다.
10
+ - 표면이 없는 primitive는 `glass-transparent`로 명시한다.
11
+ - `rgba`, 임의 `backdrop-blur`, 임의 shadow, arbitrary `[box-shadow]` 대신 glass token class를 조합한다.
14
12
 
15
13
  ## Glass Token Family
16
14
 
17
15
  실제 glass token class는 아래 family로만 작성한다.
18
16
 
19
17
  ```text
20
- glass [glass-surface-*] [glass-texture*] [glass-border*] [glass-backdrop-*] [glass-shadow-*]
18
+ (glass-transparent | glass | glass-subtle | glass-surface | glass-strong | glass-selected | glass-disabled) [glass-texture*] [glass-border*] [glass-backdrop-*] [glass-shadow-*]
21
19
  ```
22
20
 
23
- - `glass`: 기본 유리 표면을 만든다.
24
- - `glass-surface-*`: 표면의 밝기와 투명도를 고른다. `subtle`, `medium`,
25
- `strong`, `selected`, `disabled`가 있다.
21
+ - `glass-transparent`: 표면 색 없이 유리 효과의 기본 구조와 내부 효과 슬롯만 만든다. semantic `bg-*`가 표면 역할을 하거나, 표면 없이 texture/border/backdrop/shadow만 조합할 때 쓰는 primitive entry다.
22
+ - `glass`: 패널과 카드에 쓰는 기본 glass surface entry다. 가장 흔한 표면이며 `glass-transparent`와 같이 붙이지 않는다.
23
+ - `glass-subtle`: 배경과 가깝게 붙는 낮은 밀도 표면이다. 반복 카드, 리스트 row, skeleton처럼 화면에 여러 번 나오는 요소에 쓴다.
24
+ - `glass-surface`: 기본보다 더 또렷한 foreground/control 표면이다. 버튼, toolbar, segmented control, 조작 가능한 입력 wrapper처럼 사용자가 직접 조작하는 작은 표면에 쓴다.
25
+ - `glass-strong`: popover, tooltip, menu, modal 안쪽의 떠 있는 레이어처럼 배경에서 강하게 분리되어야 하는 표면에 쓴다.
26
+ - `glass-selected`: selected tab, active segmented item, selected pill처럼 선택 상태 자체를 표현하는 표면이다.
27
+ - `glass-disabled`: disabled input, locked value처럼 비활성 또는 잠긴 값을 표현하는 표면이다.
26
28
  - `glass-texture*`: 빛 하이라이트만 얹는다. 표면, 경계, blur를 만들지 않는다.
27
- - `glass-border*`: 경계, 상단 하이라이트, 안쪽 윤곽선을 만든다. 기본값,
28
- `faint`, `subtle`, `medium`, `strong`이 있다.
29
- - `glass-backdrop-*`: 뒤 배경 blur/saturate 단계만 정한다. `sm`, `md`, `lg`가
30
- 있다.
29
+ - `glass-border*`: 경계, 상단 하이라이트, 안쪽 윤곽선을 만든다. 기본값, `faint`, `subtle`, `medium`, `strong`이 있다.
30
+ - `glass-backdrop-*`: 뒤 배경 blur/saturate 단계만 정한다. `sm`, `md`, `lg`가 있다.
31
31
  - `glass-shadow-*`: elevation만 정한다. `sm`, `md`, `lg`가 있다.
32
32
 
33
- `hover:`, `focus-visible:`, `disabled:`, `rounded-*`, `p-*`, `h-*`, `w-*`,
34
- `text-*`, `flex`, `grid`는 glass token이 아니라 Tailwind 보조 유틸리티다.
33
+ `hover:`, `focus-visible:`, `disabled:`, `rounded-*`, `p-*`, `h-*`, `w-*`, `text-*`, `flex`, `grid`는 glass token이 아니라 Tailwind 보조 유틸리티다.
35
34
  토큰 조합을 정한 뒤 필요한 상태, 크기, 레이아웃 유틸리티를 붙인다.
36
35
 
37
- `bg-glass-surface-interactive`, `bg-glass-surface-selected`는 `@theme`에 노출된
38
- color utility다. hover/focus/selected 배경을 맞출 때 쓰지만,
39
- `glass-surface-*` utility family와 같은 것으로 설명하지 않는다.
36
+ `bg-glass-interactive`, `bg-glass-selected`는 `@theme`에 노출된 color utility다.
37
+ hover/focus/selected 배경을 맞출 때 쓰지만, surface entry family와 같은 것으로 설명하지 않는다.
40
38
 
41
39
  ## Surface 선택 기준
42
40
 
43
41
  - 넓은 section, form panel, summary panel:
44
42
  `glass glass-border glass-backdrop-md glass-shadow-md`
45
43
  - 반복 카드, 리스트 row, 낮은 우선순위 block:
46
- `glass glass-surface-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm`
47
- - 버튼 묶음, toolbar, segmented control:
48
- `glass glass-surface-medium glass-border-medium glass-backdrop-md glass-shadow-md`
44
+ `glass-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm`
45
+ - 버튼 묶음, toolbar, segmented control, 조작 가능한 입력 wrapper:
46
+ `glass-surface glass-border-medium glass-backdrop-md glass-shadow-md`
49
47
  - 선택된 tab, segmented item, selected pill:
50
- `glass glass-surface-selected glass-texture-subtle glass-border-subtle glass-shadow-sm`
48
+ `glass-selected glass-texture-subtle glass-border-subtle glass-shadow-sm`
51
49
  - 비활성 입력 또는 잠긴 값:
52
- `glass glass-surface-disabled glass-border-subtle glass-backdrop-sm glass-shadow-sm`
50
+ `glass-disabled glass-border-subtle glass-backdrop-sm glass-shadow-sm`
51
+ - 의미 색상 표면이 필요한 primary/destructive/semantic badge:
52
+ `glass-transparent` 위에 `bg-primary`, `bg-destructive/10`, `bg-emerald-*` 같은 semantic background를 붙인다.
53
53
 
54
- `glass-surface-medium`은 작은 control group에는 맞지만, page shell이나 넓은
55
- 카드에 반복하면 light mode에서 허옇게 뜬다. 넓은 면적은 기본 `glass` 또는
56
- `glass-surface-subtle`부터 시작한다.
54
+ `glass-surface`는 작은 control group에는 맞지만, page shell이나 넓은 카드에 반복하면 light mode에서 허옇게 뜰 수 있다.
55
+ 넓은 면적은 `glass` 또는 `glass-subtle`부터 시작한다.
57
56
 
58
57
  ## 기본 className 조합
59
58
 
@@ -63,77 +62,68 @@ color utility다. hover/focus/selected 배경을 맞출 때 쓰지만,
63
62
  <section className='glass glass-border glass-backdrop-md glass-shadow-md rounded-xl p-4 sm:p-5'>...</section>
64
63
  ```
65
64
 
66
- 폼 영역, 검색 영역, 요약 영역의 기본 표면이다. 페이지 안에서 큰 면적을
67
- 차지하면 `glass-surface-medium`을 추가하지 않는다.
65
+ 폼 영역, 검색 영역, 요약 영역의 기본 표면이다. 페이지 안에서 큰 면적을 차지하면 `glass-surface`를 기본값으로 넣지 않는다.
68
66
 
69
67
  ### Subtle Card
70
68
 
71
69
  ```tsx
72
- <article className='glass glass-surface-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm rounded-xl p-4'>
73
- ...
74
- </article>
70
+ <article className='glass-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm rounded-xl p-4'>...</article>
75
71
  ```
76
72
 
77
- 반복 카드, 보조 정보, 리스트 row, skeleton의 기본 표면이다. 같은 화면에 여러
78
- 개 반복될 때는 이 조합을 우선한다.
73
+ 반복 카드, 보조 정보, 리스트 row, skeleton의 기본 표면이다. 같은 화면에 여러 개 반복될 때는 이 조합을 우선한다.
79
74
 
80
75
  ### List Row
81
76
 
82
77
  ```tsx
83
- <div className='glass glass-surface-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm flex items-center justify-between gap-3 rounded-lg p-3'>
78
+ <div className='glass-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm flex items-center justify-between gap-3 rounded-lg p-3'>
84
79
  <span className='text-sm font-medium'>Item</span>
85
80
  <span className='text-muted-foreground text-xs'>Meta</span>
86
81
  </div>
87
82
  ```
88
83
 
89
- 리스트 안의 개별 행은 card보다 낮은 radius와 padding을 쓴다. 선택 여부는
90
- row 전체 색을 과하게 올리기보다 badge나 selected surface를 보조로 쓴다.
84
+ 리스트 안의 개별 행은 card보다 낮은 radius와 padding을 쓴다. 선택 여부는 row 전체 색을 과하게 올리기보다 badge나 selected surface를 보조로 쓴다.
91
85
 
92
86
  ### Button
93
87
 
94
88
  ```tsx
95
- <button className='glass glass-surface-medium glass-border-medium glass-backdrop-md glass-shadow-md text-foreground hover:bg-glass-surface-interactive focus-visible:ring-ring/50 inline-flex h-10 items-center justify-center rounded-lg px-4 text-sm font-semibold transition-colors focus-visible:ring-2 focus-visible:outline-none'>
89
+ <button className='glass-surface glass-border-medium glass-backdrop-md glass-shadow-md text-foreground hover:bg-glass-interactive focus-visible:ring-ring/50 inline-flex h-10 items-center justify-center rounded-lg px-4 text-sm font-semibold transition-colors focus-visible:ring-2 focus-visible:outline-none'>
96
90
  Button
97
91
  </button>
98
92
  ```
99
93
 
100
- 일반 버튼은 control surface라서 `surface-medium`을 있다. 같은 화면에서
101
- 버튼이 많이 반복되면 `surface-subtle`로 낮춘다.
94
+ 일반 버튼은 control surface라서 `glass-surface`를 쓴다. 같은 화면에서 버튼이 많이 반복되면 `glass-subtle`로 낮춘다.
102
95
 
103
96
  ### Primary Button
104
97
 
105
98
  ```tsx
106
- <button className='glass-texture-subtle glass-border-strong bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-ring/50 inline-flex h-10 items-center justify-center rounded-lg border px-4 text-sm font-semibold transition-colors focus-visible:ring-2 focus-visible:outline-none'>
99
+ <button className='glass-transparent glass-texture-subtle glass-border-strong bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-ring/50 inline-flex h-10 items-center justify-center rounded-lg border px-4 text-sm font-semibold transition-colors focus-visible:ring-2 focus-visible:outline-none'>
107
100
  Save
108
101
  </button>
109
102
  ```
110
103
 
111
- primary는 `bg-primary`가 표면 역할을 한다. `glass-surface-*`를 추가하지 않고
112
- texture와 strong border만 얹는다.
104
+ primary는 `bg-primary`가 표면 역할을 한다. `glass` 또는 `glass-surface`를 추가하지 않고 `glass-transparent` primitive entry 위에 texture와 strong border만 얹는다.
113
105
 
114
106
  ### Destructive Button
115
107
 
116
108
  ```tsx
117
- <button className='glass glass-texture glass-border-medium glass-backdrop-sm glass-shadow-sm bg-destructive/20 text-destructive hover:bg-destructive/30 focus-visible:ring-destructive/40 inline-flex h-10 items-center justify-center rounded-lg px-4 text-sm font-semibold transition-colors focus-visible:ring-2 focus-visible:outline-none'>
109
+ <button className='glass-transparent glass-texture glass-border-medium glass-backdrop-sm glass-shadow-sm bg-destructive/20 text-destructive hover:bg-destructive/30 focus-visible:ring-destructive/40 inline-flex h-10 items-center justify-center rounded-lg px-4 text-sm font-semibold transition-colors focus-visible:ring-2 focus-visible:outline-none'>
118
110
  Delete
119
111
  </button>
120
112
  ```
121
113
 
122
- 삭제, 취소, 위험 동작은 의미 색상 배경과 텍스트를 유지한다. glass는 질감,
123
- 경계, elevation만 보강한다.
114
+ 삭제, 취소, 위험 동작은 의미 색상 배경과 텍스트를 유지한다. glass는 질감, 경계, elevation만 보강한다.
124
115
 
125
116
  ### Disabled Button
126
117
 
127
118
  ```tsx
128
119
  <button
129
120
  disabled
130
- className='glass glass-surface-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm text-muted-foreground inline-flex h-10 items-center justify-center rounded-lg px-4 text-sm font-semibold opacity-60 disabled:cursor-not-allowed'>
121
+ className='glass-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm text-muted-foreground inline-flex h-10 items-center justify-center rounded-lg px-4 text-sm font-semibold opacity-60 disabled:cursor-not-allowed'>
131
122
  Disabled
132
123
  </button>
133
124
  ```
134
125
 
135
- disabled 상태는 hover/focus 효과를 늘리지 않는다. 잠긴 값이나 비활성 입력은
136
- `surface-disabled`를 쓴다.
126
+ disabled 상태는 hover/focus 효과를 늘리지 않는다. 잠긴 값이나 비활성 입력은 `glass-disabled`를 쓴다.
137
127
 
138
128
  ### Icon Button
139
129
 
@@ -141,13 +131,12 @@ disabled 상태는 hover/focus 효과를 늘리지 않는다. 잠긴 값이나
141
131
  <button
142
132
  type='button'
143
133
  aria-label='Edit'
144
- className='glass glass-surface-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm text-foreground hover:bg-glass-surface-interactive focus-visible:ring-ring/50 inline-flex size-10 items-center justify-center rounded-lg transition-colors focus-visible:ring-2 focus-visible:outline-none'>
134
+ className='glass-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm text-foreground hover:bg-glass-interactive focus-visible:ring-ring/50 inline-flex size-10 items-center justify-center rounded-lg transition-colors focus-visible:ring-2 focus-visible:outline-none'>
145
135
  <Icon className='size-5' aria-hidden='true' />
146
136
  </button>
147
137
  ```
148
138
 
149
- 아이콘 버튼은 `aria-label`을 필수로 둔다. size는 `size-10`을 기본으로 해서
150
- 일반 `h-10` 버튼과 높이를 맞춘다.
139
+ 아이콘 버튼은 `aria-label`을 필수로 둔다. size는 `size-10`을 기본으로 해서 일반 `h-10` 버튼과 높이를 맞춘다.
151
140
 
152
141
  ### Segmented Control
153
142
 
@@ -155,50 +144,47 @@ disabled 상태는 hover/focus 효과를 늘리지 않는다. 잠긴 값이나
155
144
  <div
156
145
  role='tablist'
157
146
  aria-label='Density'
158
- className='glass glass-surface-medium glass-border-medium glass-backdrop-md glass-shadow-md inline-flex rounded-lg p-1'>
147
+ className='glass-surface glass-border-medium glass-backdrop-md glass-shadow-md inline-flex rounded-lg p-1'>
159
148
  <button
160
149
  type='button'
161
150
  role='tab'
162
151
  aria-selected='true'
163
- className='glass glass-surface-selected glass-texture-subtle glass-border-subtle glass-shadow-sm text-foreground rounded-md px-3 py-1.5 text-sm font-semibold'>
152
+ className='glass-selected glass-texture-subtle glass-border-subtle glass-shadow-sm text-foreground rounded-md px-3 py-1.5 text-sm font-semibold'>
164
153
  Compact
165
154
  </button>
166
155
  <button
167
156
  type='button'
168
157
  role='tab'
169
158
  aria-selected='false'
170
- className='text-muted-foreground hover:bg-glass-surface-interactive focus-visible:ring-ring/50 rounded-md px-3 py-1.5 text-sm font-semibold transition-colors focus-visible:ring-2 focus-visible:outline-none'>
159
+ className='text-muted-foreground hover:bg-glass-interactive focus-visible:ring-ring/50 rounded-md px-3 py-1.5 text-sm font-semibold transition-colors focus-visible:ring-2 focus-visible:outline-none'>
171
160
  Comfort
172
161
  </button>
173
162
  </div>
174
163
  ```
175
164
 
176
- group 표면은 `surface-medium`, 활성 항목은 `surface-selected`로 분리한다.
177
- 비활성 항목에는 glass를 중복 적용하지 않는다.
165
+ group 표면은 `glass-surface`, 활성 항목은 `glass-selected`로 분리한다. 비활성 항목에는 glass를 중복 적용하지 않는다.
178
166
 
179
167
  ### Input
180
168
 
181
169
  ```tsx
182
170
  <input
183
- className='glass glass-surface-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm text-foreground placeholder:text-muted-foreground/70 focus-visible:bg-glass-surface-selected focus-visible:ring-ring/50 h-10 w-full rounded-lg px-3 text-sm transition-colors outline-none focus-visible:ring-2'
171
+ className='glass-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm text-foreground placeholder:text-muted-foreground/70 focus-visible:bg-glass-selected focus-visible:ring-ring/50 h-10 w-full rounded-lg px-3 text-sm transition-colors outline-none focus-visible:ring-2'
184
172
  placeholder='Search'
185
173
  />
186
174
  ```
187
175
 
188
- 기본 입력은 `surface-subtle`로 낮춘다. 버튼과 나란히 놓이는 검색/필터 입력은
189
- `h-10`, 테이블이나 인라인 편집 입력은 `h-9`를 쓴다.
176
+ 기본 입력은 `glass-subtle`로 낮춘다. 버튼과 나란히 놓이는 검색/필터 입력은 `h-10`, 테이블이나 인라인 편집 입력은 `h-9`를 쓴다.
190
177
 
191
178
  ### Search Input
192
179
 
193
180
  ```tsx
194
- <div className='glass glass-surface-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm focus-within:bg-glass-surface-selected focus-within:ring-ring/50 flex h-10 w-full items-center gap-2 rounded-lg px-3 transition-colors focus-within:ring-2'>
181
+ <div className='glass-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm focus-within:bg-glass-selected focus-within:ring-ring/50 flex h-10 w-full items-center gap-2 rounded-lg px-3 transition-colors focus-within:ring-2'>
195
182
  <Icon className='text-muted-foreground size-4 shrink-0' aria-hidden='true' />
196
183
  <input className='placeholder:text-muted-foreground/70 min-w-0 flex-1 bg-transparent text-sm outline-none' />
197
184
  </div>
198
185
  ```
199
186
 
200
- 아이콘이 들어간 검색 입력은 wrapper가 glass 표면을 담당하고, 내부 input은
201
- `bg-transparent`로 둔다.
187
+ 아이콘이 들어간 검색 입력은 wrapper가 surface entry를 담당하고, 내부 input은 `bg-transparent`로 둔다.
202
188
 
203
189
  ### Error Input
204
190
 
@@ -206,12 +192,11 @@ group 표면은 `surface-medium`, 활성 항목은 `surface-selected`로 분리
206
192
  <input
207
193
  aria-invalid='true'
208
194
  aria-describedby='field-error'
209
- className='glass glass-backdrop-md glass-shadow-md border-destructive text-foreground focus-visible:ring-destructive/30 h-10 w-full rounded-lg border px-3 text-sm outline-none focus-visible:ring-2'
195
+ className='glass text-foreground focus-visible:ring-destructive/30 border-destructive h-10 w-full rounded-lg border px-3 text-sm outline-none focus-visible:ring-2'
210
196
  />
211
197
  ```
212
198
 
213
- 오류 입력은 glass border 단계보다 `border-destructive`와 오류 focus ring을
214
- 우선한다. 오류 메시지는 `aria-describedby`로 연결한다.
199
+ 오류 입력은 glass border 단계보다 `border-destructive`와 오류 focus ring을 우선한다. 오류 메시지는 `aria-describedby`로 연결한다.
215
200
 
216
201
  ### Disabled Input
217
202
 
@@ -219,26 +204,24 @@ group 표면은 `surface-medium`, 활성 항목은 `surface-selected`로 분리
219
204
  <input
220
205
  disabled
221
206
  readOnly
222
- className='glass glass-surface-disabled glass-border-subtle glass-backdrop-sm glass-shadow-sm text-foreground/45 placeholder:text-foreground/35 dark:text-foreground/40 dark:placeholder:text-foreground/30 h-10 w-full cursor-not-allowed rounded-lg px-3 text-sm font-medium disabled:opacity-100'
207
+ className='glass-disabled glass-border-subtle glass-backdrop-sm glass-shadow-sm text-foreground/45 placeholder:text-foreground/35 dark:text-foreground/40 dark:placeholder:text-foreground/30 h-10 w-full cursor-not-allowed rounded-lg px-3 text-sm font-medium disabled:opacity-100'
223
208
  />
224
209
  ```
225
210
 
226
- 비활성 입력은 opacity만 낮추지 말고 `surface-disabled`를 쓴다. 값이 잠긴
227
- 상태라면 `readOnly` 여부도 함께 명확히 한다.
211
+ 비활성 입력은 opacity만 낮추지 말고 `glass-disabled`를 쓴다. 값이 잠긴 상태라면 `readOnly` 여부도 함께 명확히 한다.
228
212
 
229
213
  ### Textarea
230
214
 
231
215
  ```tsx
232
- <textarea className='glass glass-surface-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm text-foreground placeholder:text-muted-foreground/70 focus-visible:bg-glass-surface-selected focus-visible:ring-ring/50 min-h-28 w-full resize-y rounded-lg px-3 py-2.5 text-sm transition-colors outline-none focus-visible:ring-2' />
216
+ <textarea className='glass-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm text-foreground placeholder:text-muted-foreground/70 focus-visible:bg-glass-selected focus-visible:ring-ring/50 min-h-28 w-full resize-y rounded-lg px-3 py-2.5 text-sm transition-colors outline-none focus-visible:ring-2' />
233
217
  ```
234
218
 
235
- textarea도 input과 같은 표면 규칙을 따른다. placeholder만 label처럼 쓰지
236
- 않고, 실제 label 또는 `aria-label`을 제공한다.
219
+ textarea도 input과 같은 표면 규칙을 따른다. placeholder만 label처럼 쓰지 않고, 실제 label 또는 `aria-label`을 제공한다.
237
220
 
238
221
  ### Checkbox Row
239
222
 
240
223
  ```tsx
241
- <label className='glass glass-surface-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm flex items-center gap-3 rounded-lg p-3 text-sm'>
224
+ <label className='glass-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm flex items-center gap-3 rounded-lg p-3 text-sm'>
242
225
  <input type='checkbox' className='text-primary size-4 rounded' />
243
226
  <span>
244
227
  <span className='block font-medium'>Compressed mode</span>
@@ -247,66 +230,61 @@ textarea도 input과 같은 표면 규칙을 따른다. placeholder만 label처
247
230
  </label>
248
231
  ```
249
232
 
250
- checkbox 자체는 표준 form control을 유지하고, 설명이 필요한 선택지만 row에
251
- glass 표면을 준다.
233
+ checkbox 자체는 표준 form control을 유지하고, 설명이 필요한 선택지만 row에 glass 표면을 준다.
252
234
 
253
235
  ### Status Message
254
236
 
255
237
  ```tsx
256
238
  <div
257
239
  role='status'
258
- className='glass glass-surface-medium glass-border-medium glass-backdrop-md glass-shadow-md rounded-lg p-4 text-sm'>
240
+ className='glass-surface glass-border-medium glass-backdrop-md glass-shadow-md rounded-lg p-4 text-sm'>
259
241
  <p className='font-semibold'>Saved</p>
260
242
  <p className='text-muted-foreground mt-1'>Changes were applied.</p>
261
243
  </div>
262
244
  ```
263
245
 
264
- 일반 상태 메시지는 텍스트 의미를 우선한다. 성공, 안내, 저장 완료처럼 짧게
265
- 노출되는 상태에 쓴다.
246
+ 일반 상태 메시지는 텍스트 의미를 우선한다. 성공, 안내, 저장 완료처럼 짧게 노출되는 상태에 쓴다.
266
247
 
267
248
  ### Error Message
268
249
 
269
250
  ```tsx
270
251
  <div
271
252
  role='alert'
272
- className='glass-texture border-destructive/50 bg-destructive/10 text-destructive rounded-lg border p-4 text-sm'>
253
+ className='glass-transparent glass-texture border-destructive/50 bg-destructive/10 text-destructive rounded-lg border p-4 text-sm'>
273
254
  <p className='font-semibold'>Error</p>
274
255
  <p className='mt-1'>Required token is missing.</p>
275
256
  </div>
276
257
  ```
277
258
 
278
- 오류 표면은 의미 색상 배경과 경계를 우선한다. `glass-surface-medium`으로
279
- 오류를 덮지 않는다.
259
+ 오류 표면은 의미 색상 배경과 경계를 우선한다. `glass-surface`로 오류를 덮지 않는다.
280
260
 
281
261
  ### Badge
282
262
 
283
263
  ```tsx
284
- <span className='glass glass-texture-subtle glass-border-subtle glass-backdrop-sm bg-muted/45 text-muted-foreground inline-flex items-center rounded-full border px-3 py-1 text-xs font-semibold'>
264
+ <span className='glass-transparent glass-texture-subtle glass-border-subtle glass-backdrop-sm bg-muted/45 text-muted-foreground inline-flex items-center rounded-full border px-3 py-1 text-xs font-semibold'>
285
265
  Draft
286
266
  </span>
287
267
  ```
288
268
 
289
269
  ```tsx
290
- <span className='glass glass-texture glass-border-subtle glass-backdrop-sm inline-flex items-center rounded-full border bg-emerald-500/20 px-3 py-1 text-xs font-semibold text-emerald-950 dark:text-emerald-50'>
270
+ <span className='glass-transparent glass-texture glass-border-subtle glass-backdrop-sm inline-flex items-center rounded-full border bg-emerald-500/20 px-3 py-1 text-xs font-semibold text-emerald-950 dark:text-emerald-50'>
291
271
  Active
292
272
  </span>
293
273
  ```
294
274
 
295
- neutral badge는 muted 배경을 쓰고, semantic badge는 의미 색상과 light/dark
296
- 텍스트 대비를 함께 지정한다.
275
+ neutral badge는 muted 배경을 쓰고, semantic badge는 의미 색상과 light/dark 텍스트 대비를 함께 지정한다.
297
276
 
298
277
  ### Skeleton
299
278
 
300
279
  ```tsx
301
- <div className='glass glass-surface-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm w-full space-y-3 rounded-xl p-4 motion-safe:animate-pulse motion-reduce:animate-none'>
280
+ <div className='glass-subtle glass-border-subtle glass-backdrop-sm glass-shadow-sm w-full space-y-3 rounded-xl p-4 motion-safe:animate-pulse motion-reduce:animate-none'>
302
281
  <div className='bg-muted/70 h-3 w-3/5 rounded-full' />
303
282
  <div className='bg-muted/50 h-3 rounded-full' />
304
283
  <div className='bg-muted/40 h-3 w-4/5 rounded-full' />
305
284
  </div>
306
285
  ```
307
286
 
308
- skeleton은 낮은 표면과 muted block만 쓴다. motion은 `motion-reduce` 대응을
309
- 항상 같이 둔다.
287
+ skeleton은 낮은 표면과 muted block만 쓴다. motion은 `motion-reduce` 대응을 항상 같이 둔다.
310
288
 
311
289
  ### Empty State
312
290
 
@@ -317,38 +295,32 @@ skeleton은 낮은 표면과 muted block만 쓴다. motion은 `motion-reduce`
317
295
  </div>
318
296
  ```
319
297
 
320
- empty state는 정보 밀도가 낮으므로 기본 `glass`와 낮은 shadow를 쓴다. 가능한
321
- 다음 행동을 짧은 문장으로 알려준다.
298
+ empty state는 정보 밀도가 낮으므로 기본 surface와 낮은 shadow를 쓴다. 가능한 다음 행동을 짧은 문장으로 알려준다.
322
299
 
323
300
  ## 작성 규칙
324
301
 
325
- - 먼저 요소 역할에 맞는 glass token 조합을 고른다.
326
- - 넓은 표면에는 `surface-medium`을 기본값으로 넣지 않는다.
302
+ - 먼저 요소 역할에 맞는 glass entry를 하나만 고른다.
303
+ - 표면이 필요한 컴포넌트는 `glass`, `glass-subtle`, `glass-surface`, `glass-strong`, `glass-selected`, `glass-disabled` 중 하나를 entry로 쓴다.
304
+ - semantic 배경이 표면 역할을 하는 컴포넌트는 `glass-transparent`를 entry로 쓰고 surface entry를 붙이지 않는다.
305
+ - `glass-transparent`는 완전한 surface-less primitive다. background, backdrop-filter, border color, shadow를 직접 소유하지 않는다.
306
+ - 넓은 표면에는 `glass-surface`를 기본값으로 넣지 않는다.
327
307
  - `glass-texture*`만으로 표면을 만들었다고 가정하지 않는다.
328
- - semantic 상태는 `bg-primary`, `bg-destructive`, `bg-emerald-*`,
329
- `bg-amber-*`, `bg-sky-*`, `bg-rose-*` 같은 의미 색상을 유지한다.
330
- - 모든 nested child를 glass card로 만들지 않는다. 역할이 없는 중첩은 spacing,
331
- divider, typography로 해결한다.
308
+ - semantic 상태는 `bg-primary`, `bg-destructive`, `bg-emerald-*`, `bg-amber-*`, `bg-sky-*`, `bg-rose-*` 같은 의미 색상을 유지한다.
309
+ - 모든 nested child를 glass card로 만들지 않는다. 역할이 없는 중첩은 spacing, divider, typography로 해결한다.
332
310
 
333
311
  ## 금지 패턴
334
312
 
335
- - `bg-background/45`, `ring-border/15`, 임의 `shadow-sm`, 임의
336
- `backdrop-blur-*`, arbitrary `[box-shadow]`, inline `rgba()`로 glass새로
337
- 만들지 않는다.
338
- - 기본 className 조합에서 `glass-surface-strong`, `glass-border-strong`,
339
- `glass-backdrop-lg`, `glass-shadow-lg`를 일반 카드나 패널에 쓰지 않는다.
313
+ - `bg-background/45`, `ring-border/15`, 임의 `shadow-sm`, 임의 `backdrop-blur-*`, arbitrary `[box-shadow]`, inline `rgba()`로 glass를 새로 만들지 않는다.
314
+ - `glass-transparent glass`처럼 entry utility두 개 같이 붙이지 않는다.
315
+ - `glass glass-subtle`, `glass glass-surface`, `glass-subtle glass-surface`처럼 surface entry를 한 요소에 두 개 이상 붙이지 않는다.
316
+ - 기본 className 조합에서 `glass-strong`, `glass-border-strong`, `glass-backdrop-lg`, `glass-shadow-lg`를 일반 카드나 패널에 쓰지 않는다.
340
317
  - 동일 화면에서 버튼, 입력, badge의 radius와 높이를 제각각 만들지 않는다.
341
318
  - placeholder만 label처럼 쓰지 않는다.
342
319
 
343
320
  ## Accessibility
344
321
 
345
- - interactive element는 `focus-visible:ring-2 focus-visible:outline-none`와
346
- 적절한 `focus-visible:ring-*`를 유지한다.
347
- - icon-only button은 `aria-label`을 제공하고, 장식 icon에는 `aria-hidden`을
348
- 둔다.
349
- - input/textarea는 label, `aria-label`, `aria-describedby`, error message를
350
- 상황에 맞게 연결한다.
351
- - 비활성 상태는 `disabled:cursor-not-allowed`, `disabled:opacity-*`,
352
- `surface-disabled` 중 역할에 맞는 조합을 쓴다.
353
- - reduced transparency, high contrast, forced colors fallback은
354
- `globals.css`가 담당한다. 컴포넌트에서 custom media query로 우회하지 않는다.
322
+ - interactive element는 `focus-visible:ring-2 focus-visible:outline-none`와 적절한 `focus-visible:ring-*`를 유지한다.
323
+ - icon-only button은 `aria-label`을 제공하고, 장식 icon에는 `aria-hidden`을 둔다.
324
+ - input/textarea는 label, `aria-label`, `aria-describedby`, error message를 상황에 맞게 연결한다.
325
+ - 비활성 상태는 `disabled:cursor-not-allowed`, `disabled:opacity-*`, `glass-disabled` 중 역할에 맞는 조합을 쓴다.
326
+ - reduced transparency, high contrast, forced colors fallback은 `globals.css`가 담당한다. 컴포넌트에서 custom media query로 우회하지 않는다.
@@ -72,9 +72,10 @@
72
72
  --color-code-number: var(--code-number);
73
73
  --color-selection: var(--selection);
74
74
  --color-selection-foreground: var(--selection-foreground);
75
+ --color-glass: var(--glass);
75
76
  --color-glass-surface: var(--glass-surface);
76
- --color-glass-surface-interactive: var(--glass-surface-interactive);
77
- --color-glass-surface-selected: var(--glass-surface-selected);
77
+ --color-glass-interactive: var(--glass-interactive);
78
+ --color-glass-selected: var(--glass-selected);
78
79
  }
79
80
 
80
81
  :root {
@@ -123,13 +124,13 @@
123
124
  /************************************************************/
124
125
  /* liquid glass surface inputs (light) */
125
126
  /************************************************************/
127
+ --glass: oklch(0.968 0.007 247 / 0.3);
128
+ --glass-subtle: oklch(0.968 0.007 247 / 0.18);
126
129
  --glass-surface: oklch(0.968 0.007 247 / 0.42);
127
- --glass-surface-subtle: oklch(0.968 0.007 247 / 0.3);
128
- --glass-surface-medium: oklch(0.982 0.006 247 / 0.58);
129
- --glass-surface-strong: oklch(0.992 0.004 247 / 0.74);
130
- --glass-surface-interactive: oklch(0.92 0.006 247 / 0.35);
131
- --glass-surface-selected: oklch(0.93 0.006 247 / 0.5);
132
- --glass-surface-disabled: oklch(0.9 0.006 247 / 0.25);
130
+ --glass-strong: oklch(0.992 0.004 247 / 0.74);
131
+ --glass-interactive: oklch(0.92 0.006 247 / 0.35);
132
+ --glass-selected: oklch(0.93 0.006 247 / 0.5);
133
+ --glass-disabled: oklch(0.9 0.006 247 / 0.25);
133
134
  --glass-border-faint: oklch(0.929 0.013 255 / 0.16);
134
135
  --glass-border-subtle: oklch(0.929 0.013 255 / 0.24);
135
136
  --glass-border: oklch(0.929 0.013 255 / 0.28);
@@ -155,24 +156,24 @@
155
156
  linear-gradient(180deg, oklch(1 0 0 / 0.58) 0%, oklch(1 0 0 / 0.24) 20%, transparent 60%),
156
157
  linear-gradient(115deg, oklch(1 0 0 / 0.26) 0%, transparent 34%, oklch(1 0 0 / 0.12) 100%),
157
158
  radial-gradient(140% 120% at 18% 0%, oklch(1 0 0 / 0.3), transparent 46%);
159
+ --glass-fallback: oklch(0.968 0.007 247 / 0.88);
160
+ --glass-subtle-fallback: oklch(0.968 0.007 247 / 0.78);
158
161
  --glass-surface-fallback: oklch(0.968 0.007 247 / 0.94);
159
- --glass-surface-subtle-fallback: oklch(0.968 0.007 247 / 0.88);
160
- --glass-surface-medium-fallback: oklch(0.968 0.007 247 / 0.97);
161
- --glass-surface-selected-fallback: oklch(0.94 0.006 247 / 0.96);
162
- --glass-surface-strong-fallback: oklch(0.968 0.007 247 / 0.99);
163
- --glass-surface-disabled-fallback: oklch(0.92 0.006 247 / 0.94);
162
+ --glass-selected-fallback: oklch(0.94 0.006 247 / 0.96);
163
+ --glass-strong-fallback: oklch(0.968 0.007 247 / 0.99);
164
+ --glass-disabled-fallback: oklch(0.92 0.006 247 / 0.94);
164
165
  --glass-backdrop-sm: blur(4px) saturate(180%);
165
166
  --glass-backdrop-md: blur(8px) saturate(180%);
166
167
  --glass-backdrop-lg: blur(16px) saturate(180%);
167
168
 
168
- --mesh-1: oklch(0.6008 0.1493 249.6 / 0.0923);
169
- --mesh-2: oklch(0.6498 0.1201 300.4 / 0.0736);
170
- --mesh-3: oklch(0.7 0.1201 220.3 / 0.0554);
171
- --mesh-4: oklch(0.5994 0.1998 320.1 / 0.1107);
169
+ --mesh-1: oklch(0.6008 0.1493 249.6 / 0.1053);
170
+ --mesh-2: oklch(0.6498 0.1201 300.4 / 0.0839);
171
+ --mesh-3: oklch(0.7 0.1201 220.3 / 0.0632);
172
+ --mesh-4: oklch(0.5994 0.1998 320.1 / 0.1262);
172
173
 
173
- --aurora-1: oklch(0.6496 0.1802 250.1 / 0.1475);
174
- --aurora-2: oklch(0.7006 0.1494 279.7 / 0.1475);
175
- --aurora-3: oklch(0.7492 0.1199 200.4 / 0.1107);
174
+ --aurora-1: oklch(0.6496 0.1802 250.1 / 0.1682);
175
+ --aurora-2: oklch(0.7006 0.1494 279.7 / 0.1682);
176
+ --aurora-3: oklch(0.7492 0.1199 200.4 / 0.1262);
176
177
 
177
178
  --noise-opacity: 0.025;
178
179
  }
@@ -222,13 +223,13 @@
222
223
  /************************************************************/
223
224
  /* liquid glass surface inputs (dark) */
224
225
  /************************************************************/
226
+ --glass: oklch(1 0 0 / 0.03);
227
+ --glass-subtle: oklch(1 0 0 / 0.015);
225
228
  --glass-surface: oklch(1 0 0 / 0.07);
226
- --glass-surface-subtle: oklch(1 0 0 / 0.03);
227
- --glass-surface-medium: oklch(1 0 0 / 0.17);
228
- --glass-surface-strong: oklch(1 0 0 / 0.25);
229
- --glass-surface-interactive: var(--glass-surface-medium);
230
- --glass-surface-selected: oklch(1 0 0 / 0.23);
231
- --glass-surface-disabled: oklch(1 0 0 / 0.06);
229
+ --glass-strong: oklch(1 0 0 / 0.25);
230
+ --glass-interactive: oklch(1 0 0 / 0.205);
231
+ --glass-selected: oklch(1 0 0 / 0.23);
232
+ --glass-disabled: oklch(1 0 0 / 0.06);
232
233
  --glass-border-faint: oklch(1 0 0 / 0.03);
233
234
  --glass-border-subtle: oklch(1 0 0 / 0.06);
234
235
  --glass-border: oklch(1 0 0 / 0.07);
@@ -254,24 +255,24 @@
254
255
  linear-gradient(180deg, oklch(1 0 0 / 0.42) 0%, oklch(1 0 0 / 0.16) 20%, transparent 58%),
255
256
  linear-gradient(115deg, oklch(1 0 0 / 0.22) 0%, transparent 36%, oklch(1 0 0 / 0.08) 100%),
256
257
  radial-gradient(140% 120% at 18% 0%, oklch(1 0 0 / 0.22), transparent 48%);
258
+ --glass-fallback: oklch(0.208 0.042 265 / 0.9);
259
+ --glass-subtle-fallback: oklch(0.208 0.042 265 / 0.82);
257
260
  --glass-surface-fallback: oklch(0.208 0.042 265 / 0.85);
258
- --glass-surface-subtle-fallback: oklch(0.208 0.042 265 / 0.9);
259
- --glass-surface-medium-fallback: oklch(0.208 0.042 265 / 0.8);
260
- --glass-surface-selected-fallback: oklch(0.208 0.042 265 / 0.76);
261
- --glass-surface-strong-fallback: oklch(0.208 0.042 265 / 0.75);
262
- --glass-surface-disabled-fallback: oklch(0.12 0.012 265 / 0.9);
261
+ --glass-selected-fallback: oklch(0.208 0.042 265 / 0.76);
262
+ --glass-strong-fallback: oklch(0.208 0.042 265 / 0.75);
263
+ --glass-disabled-fallback: oklch(0.12 0.012 265 / 0.9);
263
264
  --glass-backdrop-sm: blur(4px) saturate(180%);
264
265
  --glass-backdrop-md: blur(8px) saturate(180%);
265
266
  --glass-backdrop-lg: blur(16px) saturate(180%);
266
267
 
267
- --mesh-1: oklch(0.4035 0.121 252.1 / 0.0733);
268
- --mesh-2: oklch(0.4504 0.1802 299.9 / 0.0585);
269
- --mesh-3: oklch(0.5014 0.0917 220.6 / 0.0439);
270
- --mesh-4: oklch(0.5016 0.2405 320.2 / 0.0146);
268
+ --mesh-1: oklch(0.4035 0.121 252.1 / 0.1109);
269
+ --mesh-2: oklch(0.4504 0.1802 299.9 / 0.0884);
270
+ --mesh-3: oklch(0.5014 0.0917 220.6 / 0.0664);
271
+ --mesh-4: oklch(0.5016 0.2405 320.2 / 0.0221);
271
272
 
272
- --aurora-1: oklch(0.5057 0.1589 253.6 / 0.0733);
273
- --aurora-2: oklch(0.4499 0.2002 280 / 0.0733);
274
- --aurora-3: oklch(0.5581 0.0949 201.4 / 0.0585);
273
+ --aurora-1: oklch(0.5057 0.1589 253.6 / 0.1109);
274
+ --aurora-2: oklch(0.4499 0.2002 280 / 0.1109);
275
+ --aurora-3: oklch(0.5581 0.0949 201.4 / 0.0884);
275
276
 
276
277
  --noise-opacity: 0.02;
277
278
  }
@@ -337,40 +338,76 @@
337
338
  /************************************************************/
338
339
  /* liquid glass effect utilities */
339
340
  /************************************************************/
340
- @utility glass {
341
+ @property --glass-border-slot {
342
+ syntax: '<color>';
343
+ inherits: false;
344
+ initial-value: transparent;
345
+ }
346
+
347
+ @property --glass-border-top-slot {
348
+ syntax: '<color>';
349
+ inherits: false;
350
+ initial-value: transparent;
351
+ }
352
+
353
+ @property --glass-edge-highlight {
354
+ syntax: '<color>';
355
+ inherits: false;
356
+ initial-value: transparent;
357
+ }
358
+
359
+ @property --glass-edge-outline {
360
+ syntax: '<color>';
361
+ inherits: false;
362
+ initial-value: transparent;
363
+ }
364
+
365
+ @property --glass-shadow-slot {
366
+ syntax: '*';
367
+ inherits: false;
368
+ initial-value: 0 0 #0000;
369
+ }
370
+
371
+ @utility glass-transparent {
341
372
  background-clip: padding-box;
342
- background-color: var(--glass-surface-slot, var(--glass-surface));
343
373
  border-color: var(--glass-border-slot, transparent);
344
374
  border-top-color: var(--glass-border-top-slot, var(--glass-border-slot, transparent));
345
375
  box-shadow:
346
376
  var(--glass-shadow-slot, 0 0 #0000),
347
- inset 0 var(--glass-edge-highlight-offset, 1.75px) 0 var(--glass-edge-highlight-spread, -0.75px) var(--glass-edge-highlight, transparent),
377
+ inset 0 var(--glass-edge-highlight-offset, 1.75px) 0 var(--glass-edge-highlight-spread, -0.75px)
378
+ var(--glass-edge-highlight, transparent),
348
379
  inset 0 var(--glass-edge-outline-offset-slot, -0.5px) 0 var(--glass-edge-outline, transparent);
349
380
  }
350
381
 
351
- @utility glass-surface-subtle {
352
- --glass-surface-slot: var(--glass-surface-subtle);
353
- background-color: var(--glass-surface-subtle);
382
+ /* Surface utilities are glass entry points with owned background color. */
383
+ @utility glass {
384
+ @apply glass-transparent;
385
+ background-color: var(--glass);
386
+ }
387
+
388
+ @utility glass-subtle {
389
+ @apply glass-transparent;
390
+ background-color: var(--glass-subtle);
354
391
  }
355
392
 
356
- @utility glass-surface-medium {
357
- --glass-surface-slot: var(--glass-surface-medium);
358
- background-color: var(--glass-surface-medium);
393
+ @utility glass-surface {
394
+ @apply glass-transparent;
395
+ background-color: var(--glass-surface);
359
396
  }
360
397
 
361
- @utility glass-surface-strong {
362
- --glass-surface-slot: var(--glass-surface-strong);
363
- background-color: var(--glass-surface-strong);
398
+ @utility glass-strong {
399
+ @apply glass-transparent;
400
+ background-color: var(--glass-strong);
364
401
  }
365
402
 
366
- @utility glass-surface-selected {
367
- --glass-surface-slot: var(--glass-surface-selected);
368
- background-color: var(--glass-surface-selected);
403
+ @utility glass-selected {
404
+ @apply glass-transparent;
405
+ background-color: var(--glass-selected);
369
406
  }
370
407
 
371
- @utility glass-surface-disabled {
372
- --glass-surface-slot: var(--glass-surface-disabled);
373
- background-color: var(--glass-surface-disabled);
408
+ @utility glass-disabled {
409
+ @apply glass-transparent;
410
+ background-color: var(--glass-disabled);
374
411
  }
375
412
 
376
413
  @utility glass-texture-subtle {
@@ -482,26 +519,14 @@
482
519
 
483
520
  @utility glass-shadow-sm {
484
521
  --glass-shadow-slot: var(--glass-shadow-sm);
485
- box-shadow:
486
- var(--glass-shadow-slot),
487
- inset 0 var(--glass-edge-highlight-offset, 1.75px) 0 var(--glass-edge-highlight-spread, -0.75px) var(--glass-edge-highlight, transparent),
488
- inset 0 var(--glass-edge-outline-offset-slot, -0.5px) 0 var(--glass-edge-outline, transparent);
489
522
  }
490
523
 
491
524
  @utility glass-shadow-md {
492
525
  --glass-shadow-slot: var(--glass-shadow-md);
493
- box-shadow:
494
- var(--glass-shadow-slot),
495
- inset 0 var(--glass-edge-highlight-offset, 1.75px) 0 var(--glass-edge-highlight-spread, -0.75px) var(--glass-edge-highlight, transparent),
496
- inset 0 var(--glass-edge-outline-offset-slot, -0.5px) 0 var(--glass-edge-outline, transparent);
497
526
  }
498
527
 
499
528
  @utility glass-shadow-lg {
500
529
  --glass-shadow-slot: var(--glass-shadow-lg);
501
- box-shadow:
502
- var(--glass-shadow-slot),
503
- inset 0 var(--glass-edge-highlight-offset, 1.75px) 0 var(--glass-edge-highlight-spread, -0.75px) var(--glass-edge-highlight, transparent),
504
- inset 0 var(--glass-edge-outline-offset-slot, -0.5px) 0 var(--glass-edge-outline, transparent);
505
530
  }
506
531
 
507
532
  @utility glass-backdrop-sm {
@@ -531,27 +556,27 @@
531
556
  }
532
557
 
533
558
  .glass {
534
- background: var(--glass-surface-fallback);
559
+ background: var(--glass-fallback);
535
560
  }
536
561
 
537
- .glass-surface-subtle {
538
- background: var(--glass-surface-subtle-fallback);
562
+ .glass-subtle {
563
+ background: var(--glass-subtle-fallback);
539
564
  }
540
565
 
541
- .glass-surface-medium {
542
- background: var(--glass-surface-medium-fallback);
566
+ .glass-surface {
567
+ background: var(--glass-surface-fallback);
543
568
  }
544
569
 
545
- .glass-surface-selected {
546
- background: var(--glass-surface-selected-fallback);
570
+ .glass-selected {
571
+ background: var(--glass-selected-fallback);
547
572
  }
548
573
 
549
- .glass-surface-strong {
550
- background: var(--glass-surface-strong-fallback);
574
+ .glass-strong {
575
+ background: var(--glass-strong-fallback);
551
576
  }
552
577
 
553
- .glass-surface-disabled {
554
- background: var(--glass-surface-disabled-fallback);
578
+ .glass-disabled {
579
+ background: var(--glass-disabled-fallback);
555
580
  }
556
581
 
557
582
  .glass-texture-subtle,
@@ -570,36 +595,38 @@
570
595
  backdrop-filter: none;
571
596
  }
572
597
 
573
- .glass-shadow-sm,
574
- .glass-shadow-md,
575
- .glass-shadow-lg {
598
+ :is(.glass-transparent, .glass-surface, .glass, .glass-subtle, .glass-selected, .glass-strong, .glass-disabled):is(
599
+ .glass-shadow-sm,
600
+ .glass-shadow-md,
601
+ .glass-shadow-lg
602
+ ) {
576
603
  box-shadow:
577
604
  0 1px 2px var(--glass-shadow-color),
578
605
  inset 0 0 0 1px var(--glass-contrast-outline);
579
606
  }
580
607
 
581
608
  .glass {
582
- background: var(--glass-surface-fallback);
609
+ background: var(--glass-fallback);
583
610
  }
584
611
 
585
- .glass-surface-subtle {
586
- background: var(--glass-surface-subtle-fallback);
612
+ .glass-subtle {
613
+ background: var(--glass-subtle-fallback);
587
614
  }
588
615
 
589
- .glass-surface-medium {
590
- background: var(--glass-surface-medium-fallback);
616
+ .glass-surface {
617
+ background: var(--glass-surface-fallback);
591
618
  }
592
619
 
593
- .glass-surface-selected {
594
- background: var(--glass-surface-selected-fallback);
620
+ .glass-selected {
621
+ background: var(--glass-selected-fallback);
595
622
  }
596
623
 
597
- .glass-surface-strong {
598
- background: var(--glass-surface-strong-fallback);
624
+ .glass-strong {
625
+ background: var(--glass-strong-fallback);
599
626
  }
600
627
 
601
- .glass-surface-disabled {
602
- background: var(--glass-surface-disabled-fallback);
628
+ .glass-disabled {
629
+ background: var(--glass-disabled-fallback);
603
630
  }
604
631
 
605
632
  .glass-texture-subtle,
@@ -618,34 +645,36 @@
618
645
  backdrop-filter: none;
619
646
  }
620
647
 
621
- .glass-shadow-sm,
622
- .glass-shadow-md,
623
- .glass-shadow-lg {
648
+ :is(.glass-transparent, .glass-surface, .glass, .glass-subtle, .glass-selected, .glass-strong, .glass-disabled):is(
649
+ .glass-shadow-sm,
650
+ .glass-shadow-md,
651
+ .glass-shadow-lg
652
+ ) {
624
653
  box-shadow: inset 0 0 0 1px var(--glass-contrast-outline);
625
654
  }
626
655
 
627
656
  .glass {
628
- background: var(--glass-surface-fallback);
657
+ background: var(--glass-fallback);
629
658
  }
630
659
 
631
- .glass-surface-subtle {
632
- background: var(--glass-surface-subtle-fallback);
660
+ .glass-subtle {
661
+ background: var(--glass-subtle-fallback);
633
662
  }
634
663
 
635
- .glass-surface-medium {
636
- background: var(--glass-surface-medium-fallback);
664
+ .glass-surface {
665
+ background: var(--glass-surface-fallback);
637
666
  }
638
667
 
639
- .glass-surface-selected {
640
- background: var(--glass-surface-selected-fallback);
668
+ .glass-selected {
669
+ background: var(--glass-selected-fallback);
641
670
  }
642
671
 
643
- .glass-surface-strong {
644
- background: var(--glass-surface-strong-fallback);
672
+ .glass-strong {
673
+ background: var(--glass-strong-fallback);
645
674
  }
646
675
 
647
- .glass-surface-disabled {
648
- background: var(--glass-surface-disabled-fallback);
676
+ .glass-disabled {
677
+ background: var(--glass-disabled-fallback);
649
678
  }
650
679
 
651
680
  .glass-texture-subtle,
@@ -665,27 +694,36 @@
665
694
  }
666
695
 
667
696
  @media (forced-colors: active) {
697
+ .glass-transparent,
668
698
  .glass,
669
- .glass-surface-subtle,
670
- .glass-surface-medium,
671
- .glass-surface-selected,
672
- .glass-surface-strong,
673
- .glass-surface-disabled,
699
+ .glass-subtle,
700
+ .glass-surface,
701
+ .glass-selected,
702
+ .glass-strong,
703
+ .glass-disabled,
674
704
  .glass-texture-subtle,
675
705
  .glass-texture,
676
706
  .glass-texture-strong,
677
707
  .glass-backdrop-sm,
678
708
  .glass-backdrop-md,
679
709
  .glass-backdrop-lg {
680
- background: Canvas;
681
710
  background-image: none;
682
- color: CanvasText;
683
711
  box-shadow: none;
684
712
  filter: none;
685
713
  -webkit-backdrop-filter: none;
686
714
  backdrop-filter: none;
687
715
  }
688
716
 
717
+ .glass,
718
+ .glass-subtle,
719
+ .glass-surface,
720
+ .glass-selected,
721
+ .glass-strong,
722
+ .glass-disabled {
723
+ background: Canvas;
724
+ color: CanvasText;
725
+ }
726
+
689
727
  .glass-border,
690
728
  .glass-border-faint,
691
729
  .glass-border-subtle,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@korioinc/next-core",
3
- "version": "2.0.48",
3
+ "version": "2.0.49",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./ads": {
@@ -90,7 +90,7 @@
90
90
  "tw-animate-css": "^1.4.0",
91
91
  "typescript": "^6.0.3",
92
92
  "vitest": "^4.1.9",
93
- "@korioinc/next-configs": "2.0.48"
93
+ "@korioinc/next-configs": "2.0.49"
94
94
  },
95
95
  "dependencies": {
96
96
  "@floating-ui/react": "^0.27.19",
@@ -105,7 +105,7 @@
105
105
  "schema-dts": "^2.0.0",
106
106
  "tailwind-merge": "^3.6.0",
107
107
  "valtio": "^2.3.2",
108
- "@korioinc/next-conf": "2.0.48"
108
+ "@korioinc/next-conf": "2.0.49"
109
109
  },
110
110
  "publishConfig": {
111
111
  "access": "public",