開關(切換)
開關是一種讓人愉快的介面,可用於在兩種狀態之間切換一個值,並提供與原生核取方塊元素相同語意和鍵盤導覽功能。
首先,請透過 npm 安裝 Headless UI
npm install @headlessui/react
開關元件是使用 Switch
元件建立。您可以直接按一下元件切換開關,或在元件取得焦點時按下空白鍵切換。
切換開關時,會呼叫 onChange
函數並將 checked
值取負。
import { useState } from 'react' import { Switch } from '@headlessui/react' function MyToggle() { const [enabled, setEnabled] = useState(false) return ( <Switch checked={enabled} onChange={setEnabled} className={`${ enabled ? 'bg-blue-600' : 'bg-gray-200' } relative inline-flex h-6 w-11 items-center rounded-full`} > <span className="sr-only">Enable notifications</span> <span className={`${ enabled ? 'translate-x-6' : 'translate-x-1' } inline-block h-4 w-4 transform rounded-full bg-white transition`} /> </Switch> ) }
Headless UI 會追蹤關於各個元件的許多狀態,例如目前選取哪個開關選項、浮動選單是開啟還是關閉,或目前使用鍵盤在選單中的哪個項目是目前的焦點。
但由於元件是無形的且開箱後完全沒有設定樣式,直到您自己提供想要套用給各個狀態的樣式之前,您都無法在使用介面中看到這些資訊。
各個元件透過程用 render props 揭露其目前狀態的資訊,您可以使用它有條件地套用不同的樣式或呈現不同的內容。
例如,Switch
元件會顯示 checked
狀態,表示開關目前是否處於選取狀態。
import { useState, Fragment } from 'react' import { Switch } from '@headlessui/react' function MyToggle() { const [enabled, setEnabled] = useState(false) return ( <Switch checked={enabled} onChange={setEnabled} as={Fragment}>
{({ checked }) => (/* Use the `checked` state to conditionally style the button. */ <button className={`${checked ? 'bg-blue-600' : 'bg-gray-200'} relative inline-flex h-6 w-11 items-center rounded-full`} > <span className="sr-only">Enable notifications</span> <span className={`${checked ? 'translate-x-6' : 'translate-x-1'} inline-block h-4 w-4 transform rounded-full bg-white transition`} /> </button> )} </Switch> ) }
想了解各個元件完整的 render prop API,請參閱 元件 API 文件。
每個元件也會經由 `data-headlessui-state` 屬性顯示關於其目前的狀態資訊,你可使用該屬性有條件地套用不同的樣式。
當 渲染道具 API 中任何一種狀態為 `true` 時,這些狀態會在這項屬性中列為空白分隔的字串,讓你可以在 `[attr~=value]` 格式中,透過 CSS 屬性選取器 來針對它們。
例如,這裡是切換已開啟時,`Switch` 元件會渲染的內容
<!-- Rendered `Switch` --> <button data-headlessui-state="checked"></button>
如果你使用 Tailwind CSS,你可以使用 @headlessui/tailwindcss 外掛程式來以 `ui-checked:*` 等修改器來針對此屬性。
import { useState } from 'react' import { Switch } from '@headlessui/react' function MyToggle() { const [enabled, setEnabled] = useState(false) return ( <Switch checked={enabled} onChange={setEnabled}
className="relative inline-flex h-6 w-11 items-center rounded-full ui-checked:bg-blue-600 ui-not-checked:bg-gray-200"> <span className="sr-only">Enable notifications</span><span className="inline-block h-4 w-4 transform rounded-full bg-white transition ui-checked:translate-x-6 ui-not-checked:translate-x-1" /></Switch> ) }
預設情況下,`Switch` 會渲染一個 `button`,以及你傳遞到其中作為子項目的任何內容。這可能會讓實作特定的使用者介面變得更困難,因為子項目會巢狀在按鈕中。
在這些情況下,你可以使用 `Switch.Label` 元件以獲得更大的彈性。
此範例示範如何使用 `Switch.Group`、`Switch` 和 `Switch.Label` 元件,將標籤渲染成按鈕的兄弟項目。請注意,`Switch.Label` 會在 `Switch` 元件旁邊使用,而他們兩者都必須渲染在父層 `Switch.Group` 元件中。
import { useState } from 'react' import { Switch } from '@headlessui/react' function MyToggle() { const [enabled, setEnabled] = useState(false) return (
<Switch.Group><div className="flex items-center"><Switch.Label className="mr-4">Enable notifications</Switch.Label><Switch checked={enabled} onChange={setEnabled} className={`${ enabled ? 'bg-blue-600' : 'bg-gray-200' } relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2`} > <span className={`${ enabled ? 'translate-x-6' : 'translate-x-1' } inline-block h-4 w-4 transform rounded-full bg-white transition-transform`} /> </Switch> </div></Switch.Group>) }
預設情況下,按一下 `Switch.Label` 會切換 Switch,就像原生 HTML 核取方塊中的標籤一樣。如果你想讓標籤無法按一下(如果你設計中這樣做不合理,你可能會想這樣做),你可以將 `passive` 道具加入到 `Switch.Label` 元件中。
import { useState } from 'react' import { Switch } from '@headlessui/react' function MyToggle() { const [enabled, setEnabled] = useState(false) return ( <Switch.Group>
<Switch.Label passive>Enable notifications</Switch.Label><Switch checked={enabled} onChange={setEnabled}> {/* ... */} </Switch> </Switch.Group> ) }
如果你將 `name` 道具加入到切換中,一個隱藏的 `input` 元素將會被渲染出來,並與切換狀態保持同步。
import { useState } from 'react' import { Switch } from '@headlessui/react' function Example() { const [enabled, setEnabled] = useState(true) return ( <form action="/notification-settings" method="post">
<Switch checked={enabled} onChange={setEnabled} name="notifications">{/* ... */} </Switch> <button>Submit</button> </form> ) }
這讓你可以在原生 HTML `
指令 | 描述 |
在 | 切換切換器 |
在表單中有焦點時按一下 Enter 鍵 | 送出表單 |
屬性 | 預設值 | 描述 |
as | button | 字串 | 元件
|
checked | — | 布林值 開關是否被選取。 |
defaultChecked | — | T 使用非受控元件時,預設被選取的值。 |
onChange | — | (value: 布林值) => void 開關被切換時要呼叫的函式。 |
name | — | 字串 此元件在表單中使用時,所使用的名稱。 |
value | — | 字串 此元件在表單中使用時,如果被選取,所使用的值。 |
渲染屬性 | 描述 |
checked |
開關是否被選取。 |
屬性 | 預設值 | 描述 |
as | label | 字串 | 元件
|
passive | false | 布林值 如果為 true,則點擊標籤不會切換 |
屬性 | 預設值 | 描述 |
as | p | 字串 | 元件
|
屬性 | 預設值 | 描述 |
as | 片段 | 字串 | 元件
|