Footer
페이지 하단의 사이트 푸터 (내비게이션 섹션 + 법적 고지 블록)
목차
페이지 하단에 최대 세 블록을 세로로 쌓는 푸터입니다. 옵션 상단 구분선(showDivider), 브랜딩(aside) + 내비게이션 섹션으로 이루어진 밴드, 그리고
법적 고지 블록(회사명 · 사업자 정보 디스클로저 · 링크 줄 · 저작권)입니다. 슬롯이 빈 블록은 통째로 빠지므로, 내비게이션만 넘긴 푸터는 법적 고지 블록이 없던 때와 똑같이 그려집니다.
클래스 이름은 그대로입니다. Footer, CoreFooterContract, CoreFooterLayout,
CoreFooterStyle.
Live Preview#
코드 보기
class FooterDefaultExample extends StatelessComponent {
const FooterDefaultExample({super.key});
@override
Component build(BuildContext context) {
return Footer(
aside: div([Text('© 2026 CoUI — Industrial Ltd.')]),
sections: [
CoreFooterNavData<Component>(
title: 'Services',
children: [
div([Text('Branding')]),
div([Text('Design')]),
div([Text('Marketing')]),
],
),
CoreFooterNavData<Component>(
title: 'Company',
children: [
div([Text('About us')]),
div([Text('Contact')]),
div([Text('Jobs')]),
],
),
CoreFooterNavData<Component>(
title: 'Legal',
children: [
div([Text('Terms')]),
div([Text('Privacy')]),
div([Text('Cookies')]),
],
),
],
);
}
}
class FooterDefaultExample extends StatelessWidget {
const FooterDefaultExample({super.key});
@override
Widget build(BuildContext context) {
return Footer(
aside: const Text('© 2026 CoUI — Industrial Ltd.'),
sections: const [
CoreFooterNavData<Widget>(
title: 'Services',
children: [
Text('Branding'),
Text('Design'),
Text('Marketing'),
],
),
CoreFooterNavData<Widget>(
title: 'Company',
children: [
Text('About us'),
Text('Contact'),
Text('Jobs'),
],
),
CoreFooterNavData<Widget>(
title: 'Legal',
children: [
Text('Terms'),
Text('Privacy'),
Text('Cookies'),
],
),
],
);
}
}
개요#
이 문서는 /components/footer 에 있었습니다. 지금은 /blocks/footer 입니다. 같은 위젯이고, Dart 와 Web 의 API 이름은 바뀌지 않았습니다.
옛 주소로 들어오면 /blocks/footer 로 옮깁니다.
구조#
푸터가 직접 그리는 크롬은 배경과 패딩뿐입니다. 글자, 링크, 간격, 구분선, 디스클로저는 아래 컴포넌트를 합성합니다.
| 자리 | 컴포넌트 |
|---|---|
| 섹션 제목 · 본문 · aside · 회사명 · 저작권 | Text (호출자가 넣는 위젯) |
| 법적 링크 줄 | Link |
| 섹션 제목과 본문 사이 | Gap (sectionTitleGapStyle) |
| 상단 규칙 · 행 안 눈금 | Divider |
| 사업자 정보 | Collapsible |
aside 는 섹션보다 앞입니다. 로고나 짧은 카피를 둡니다. Figma 에서는 Aside 인스턴스 스왑과 Show aside
가 이 슬롯입니다.
sections 는 CoreFooterNavData 의 목록입니다. 각 항목은 선택적 title 과 필수 children
입니다.
사용 시기 (When to Use)#
페이지 끝에서 링크 섹션·회사 정보·저작권을 함께 묶을 때 씁니다. 선택된 목적지를 표시하고 이동 이벤트를 처리해야 하면 NavigationBar를, 사업자 정보만 접었다 펼쳐야 하면 Collapsible을 사용합니다. Footer는 페이지 흐름의 콘텐츠이며 고정 내비게이션이나 오버레이를 만들지 않습니다.
레이아웃#
축은 Layout=horizontal | vertical | center 하나뿐입니다. 멤버는 CoreFooterLayout 과 같습니다.
| 값 | 그리는 것 |
|---|---|
horizontal (기본) | aside 와 섹션이 한 줄에서 감쌉니다. 좁으면 다음 줄로 내려갑니다. |
vertical | 위→아래. 가로 축은 앞쪽(leading)입니다. |
center | 위→아래. 가로 축과 주변 텍스트를 가운데 정렬합니다. |
layout 은 내비게이션 밴드만 바꿉니다. 상단 구분선과 법적 고지 블록은 언제나 밴드 위와 아래에 세로로 쌓입니다.
위젯의 layout 이 null 이면 스타일 체인의 layout, 그다음 CoreFooterStyle.defaultLayout
(horizontal) 입니다. 테마는 CoreFooterTheme.style 만 덮고, 시맨틱 layout 을 따로 이기지 않습니다.
Figma 의 Info 는 이 축이 아닙니다. 사업자 정보 디스클로저가 펼쳐졌는지(businessInfoExpanded)입니다.
기본 사용법 (Basic Usage)#
기본 프리뷰는 horizontal 입니다. vertical 과 center 는 같은 슬롯을 그 축으로 다시 놓습니다. Widgetbook 의
$Default, $Vertical, $Center 와 같은 세 레이아웃입니다.
Footer(
aside: const Text('© 2026 CoUI — Industrial Ltd.'),
sections: const [
CoreFooterNavData<Widget>(
title: 'Services',
children: [
Text('Branding'),
Text('Design'),
Text('Marketing'),
],
),
CoreFooterNavData<Widget>(
title: 'Company',
children: [
Text('About us'),
Text('Contact'),
Text('Jobs'),
],
),
],
)
빠른 오버라이드 (Chain)#
이미 만든 Footer 인스턴스에 스타일을 빠르게 덧붙이고 싶다면 withStyle 체인을 쓸 수 있습니다. 생성자의 style 슬롯 인자와 동일하게 동작하지만, 이미 구성된 위젯 위에서 바로 이어 쓸 수 있습니다.
.surfaceContainer처럼 Core 토큰 상수 이름과 똑같은 이름의 getter도 있습니다 — withStyle을 한 번 더 줄인 sugar로, 이름이 곧 값이라(surfaceContainer ==
CoreColors.surfaceContainer) 어느 컴포넌트에서 써도 뜻이 갈리지 않으며, 위 예시처럼 withStyle 뒤에 이어붙일 수도 있습니다.
class FooterChainExample extends StatelessWidget {
const FooterChainExample({super.key});
@override
Widget build(BuildContext context) {
return Footer(
aside: const Text('© 2026 CoUI — Industrial Ltd.'),
sections: const [
CoreFooterNavData<Widget>(
title: 'Services',
children: [
Text('Branding'),
Text('Design'),
Text('Marketing'),
],
),
CoreFooterNavData<Widget>(
title: 'Company',
children: [
Text('About us'),
Text('Contact'),
Text('Jobs'),
],
),
CoreFooterNavData<Widget>(
title: 'Legal',
children: [
Text('Terms'),
Text('Privacy'),
Text('Cookies'),
],
),
],
)
.withStyle(
const CoreFooterStyle(
padding: CoreEdgeInsets.all(CoreSpace.space48),
sectionSpacing: CoreSpace.space48,
sectionTitleGapStyle: CoreGapStyle(size: CoreSpace.space12),
),
)
.surfaceContainer;
}
}
class FooterChainExample extends StatelessComponent {
const FooterChainExample({super.key});
@override
Component build(BuildContext context) {
return Footer(
aside: div([Text('© 2026 CoUI — Industrial Ltd.')]),
sections: [
CoreFooterNavData<Component>(
title: 'Services',
children: [
div([Text('Branding')]),
div([Text('Design')]),
div([Text('Marketing')]),
],
),
CoreFooterNavData<Component>(
title: 'Company',
children: [
div([Text('About us')]),
div([Text('Contact')]),
div([Text('Jobs')]),
],
),
CoreFooterNavData<Component>(
title: 'Legal',
children: [
div([Text('Terms')]),
div([Text('Privacy')]),
div([Text('Cookies')]),
],
),
],
)
.withStyle(
const CoreFooterStyle(
padding: CoreEdgeInsets.all(CoreSpace.space48),
sectionSpacing: CoreSpace.space48,
sectionTitleGapStyle: CoreGapStyle(size: CoreSpace.space12),
),
)
.surfaceContainer;
}
}
레시피#
법적 고지와 상단 구분선은 별도 레이아웃이 아닙니다. 같은 Footer 의 슬롯입니다.
코드 보기
class FooterLegalExample extends StatelessComponent {
const FooterLegalExample({super.key});
@override
Component build(BuildContext context) {
return Footer(
company: const Text('Cocode Inc.'),
businessInfoLabel: const Text('Business info'),
businessInfo: const Text(
'CEO Jane Doe · Business registration no. 123-45-67890 · '
'Seoul, Republic of Korea',
),
businessInfoExpanded: true,
links: [
Link(
href: '#',
variant: CoreLinkVariant.muted,
child: const Text('Refund policy'),
),
Link(
href: '#',
variant: CoreLinkVariant.muted,
child: const Text('Terms of service'),
),
Link(
href: '#',
variant: CoreLinkVariant.muted,
child: const Text('Privacy policy'),
),
],
copyright: const Text('© 2026 Cocode Inc. All rights reserved.'),
sections: const [],
);
}
}
class FooterLegalExample extends StatelessWidget {
const FooterLegalExample({super.key});
@override
Widget build(BuildContext context) {
return Footer(
company: const Text('Cocode Inc.'),
businessInfoLabel: const Text('Business info'),
businessInfo: const Text(
'CEO Jane Doe · Business registration no. 123-45-67890 · '
'Seoul, Republic of Korea',
),
businessInfoExpanded: true,
links: const [
Link(
href: '#',
variant: CoreLinkVariant.muted,
child: Text('Refund policy'),
),
Link(
href: '#',
variant: CoreLinkVariant.muted,
child: Text('Terms of service'),
),
Link(
href: '#',
variant: CoreLinkVariant.muted,
child: Text('Privacy policy'),
),
],
copyright: const Text('© 2026 Cocode Inc. All rights reserved.'),
sections: const [],
);
}
}
법적 고지#
스토어프론트가 공시하는 회사명, 사업자 정보, 약관 링크, 저작권입니다. 네 슬롯이 전부 비면 블록 자체가 그려지지 않습니다.
Footer(
company: const Text('Cocode Inc.'),
businessInfoLabel: const Text('Business info'),
businessInfo: const Text('CEO Jane Doe · Business registration no. 123-45-67890'),
links: const [
Link(href: '/refund', child: Text('Refund policy')),
Link(href: '/terms', child: Text('Terms of service')),
Link(href: '/privacy', child: Text('Privacy policy')),
],
copyright: const Text('© 2026 Cocode Inc. All rights reserved.'),
sections: const [],
)
-
디스클로저는 Collapsible 입니다. 푸터는
businessInfoLabel과businessInfo만 넘깁니다. businessInfo가 null 이면 트리거도 그리지 않습니다. 열 문단이 없으면 트리거가 남지 않습니다.-
회사명과 디스클로저 사이, 링크와 링크 사이의 눈금은 세로 Divider 입니다. 색과 두께는
inlineDividerStyle, 길이는inlineDividerLength입니다. links의 타입은List<W>입니다. 눈금은 항목 사이에만 들어가므로 항목이 하나면 눈금은 없습니다.
상단 구분선#
showDivider 의 기본은 꺼짐입니다 (CoreFooterContract.defaultShowDivider). 아무 말도 하지 않은 푸터는 선을 그리지 않습니다.
Footer(showDivider: true, sections: const [])
이 선은 full-bleed 입니다. 밴드의 가로 패딩 밖, 푸터의 양 끝까지입니다. 색과 두께는 dividerStyle 이고, 비워두면 Divider
의 기본값입니다.
이 블록에 없는 것#
메가 푸터, 뉴스레터, 거대 텍스트, 배경 이미지는 새 프로퍼티가 아닙니다. 위의 레이아웃과 슬롯으로 조합하거나, 나중에 별도 레시피로 둡니다. Ecommerce Footer 는 이 블록이 아닙니다.
Props / Parameters#
W는 합성 콘텐츠 타입입니다. Flutter에서는 Widget, Web에서는 Component이며, CoreFooterNavData<W>와 슬롯에 같은 플랫폼 타입을 사용합니다.
Footer#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
sections |
List<CoreFooterNavData<W>> |
필수 | 렌더링할 nav 섹션 목록 |
aside | W? | null | 브랜딩/로고 슬롯 (sections 앞에 배치) |
layout |
CoreFooterLayout? |
horizontal |
horizontal / vertical / center. null 이면 스타일 체인, 그다음 기본값 |
company |
W? |
null |
법적 고지 블록 첫 줄의 회사명. 주변 텍스트 스타일은
companyTextStyle
이 심으므로 평범한
Text('…')
가 그대로 상속받습니다
|
businessInfoLabel |
W? |
null | 사업자 정보 디스클로저의 트리거 라벨. 셰브론은 합성된 Collapsible 이 직접 그리므로 이 슬롯은 라벨만 담습니다 |
businessInfo |
W? |
null | 디스클로저가 여는 사업자 정보 문단. null 이면 디스클로저 자체가 없습니다 — 트리거도 셰브론도 앞의 구분 눈금도 그리지 않습니다 |
businessInfoExpanded |
bool |
false |
디스클로저의 초기 펼침 상태.
onBusinessInfoExpandedChanged
를 주지 않으면
Collapsible
이 이 값에서 시작해 스스로 토글합니다
|
onBusinessInfoExpandedChanged |
void Function(bool)? |
null | 디스클로저 토글 콜백. 넘기면 businessInfoExpanded 는 호출자가 소유하는 controlled 값이 됩니다 |
links |
List<W> |
const [] |
법적 링크 줄. 항목 사이에 hairline 눈금(Divider)이 들어갑니다. 비면 줄 자체를 그리지 않습니다 |
copyright |
W? |
null | 법적 고지 블록을 닫는 저작권 줄. 주변 텍스트 스타일은 copyrightTextStyle 이 심습니다 |
showDivider |
bool |
false |
내비게이션 밴드 위 full-bleed 상단 구분선. 기본 꺼짐 옵션 |
semanticLabel |
String? |
null | 랜드마크 이름. 생략하면 로케일 폴백(footerLabel) |
footerStyle |
CoreFooterStyle? |
null |
모든 chrome 이 지나는 단일 슬롯 (아래 표 참고) |
CoreFooterNavData<W>#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
title |
String? |
null | 섹션 제목 (titleSmall, 역할의 굵기). 없거나 빈 문자열이면 생략 |
children | List<W> | 필수 | 섹션 안의 링크/노드 목록 |
스타일 시스템 (Style System)#
CoreFooterStyle 필드#
| 필드 | 타입 | 설명 |
|---|---|---|
layout | CoreFooterLayout? | Layout mode override. |
padding |
CoreEdgeInsets? |
Padding of the content box below the opt-in top rule (pre-scaling). |
blockSpacing |
double? |
Spacing between the blocks inside the padded content box — navigation band and legal block (logical px). |
sectionSpacing |
double? |
Spacing between top-level sections (logical px). |
legalSpacing |
double? |
Spacing between the legal block's rows (logical px). |
companyRowSpacing |
double? |
Spacing inside the company row — name, tick, disclosure trigger (logical px). |
linkRowSpacing |
double? |
Spacing inside the legal link row — links and the ticks between them (logical px). |
inlineDividerLength |
double? |
Length of the hairline tick separating inline legal items (logical px, pre-scaling). Sizes the box the composed
Divider
draws into — the divider itself has no length.
|
sectionTitleGapStyle |
CoreGapStyle? |
Nested [CoreGapStyle] slot for the gap between a nav section title and its children. Forwarded to the
Gap
widget rendered between the title and the section body on Flutter, and drives the title
<div>
's inline
margin-bottom
(via
size
) on Web. Merged on top of [defaultSectionTitleGapStyle].
|
backgroundColor |
CoreColor? |
Default background colour. |
titleTextStyle |
CoreTextStyle? |
Nav section title text style override. Text colour is carried via [CoreTextStyle.color] inside this slot (sb8 — raw
textColor
field removed and folded into both this and [bodyTextStyle]).
|
bodyTextStyle |
CoreTextStyle? |
Body / link text style override. Text colour is carried via [CoreTextStyle.color] inside this slot (sb8). |
companyTextStyle |
CoreTextStyle? |
Company-name text style override, merged on top of [defaultCompanyTextStyle] and installed as the ambient text style around the
company
slot. Honoured in full — role and colour.
|
copyrightTextStyle |
CoreTextStyle? |
Copyright-line text style override, merged on top of [defaultCopyrightTextStyle] and installed as the ambient text style around the
copyright
slot. Honoured in full — role and colour.
|
dividerStyle |
CoreDividerStyle? |
Nested [CoreDividerStyle] slot for the composed top rule. Merged on top of [defaultDividerStyle] and raw-forwarded —
Divider
's own resolver fills the remaining defaults.
|
inlineDividerStyle |
CoreDividerStyle? |
Nested [CoreDividerStyle] slot for the composed hairline ticks between inline legal items. Merged on top of [defaultInlineDividerStyle] and raw-forwarded. The tick's length lives in [inlineDividerLength], not here. |
collapsibleStyle |
CoreCollapsibleStyle? |
Nested [CoreCollapsibleStyle] slot for the composed business-info disclosure — trigger typography, label ↔ chevron gap, chevron icon, expand duration. Merged on top of [defaultCollapsibleStyle] and raw-forwarded; the
Collapsible
's own resolver fills the rest.
|
Resolve chain#
모든 chrome 은 footerStyle 하나로 들어가고, 아래 순서로 합쳐집니다 — 뒤에 오는 쪽이 이깁니다.
CoreFooterStyle.defaultX // 디자인 시스템 기본값
→ CoreFooterTheme.style // 프로젝트 공통
→ 부모 컴포넌트의 슬롯 override
→ widget.footerStyle // 인스턴스별
dividerStyle / inlineDividerStyle / collapsibleStyle / sectionTitleGapStyle
은 중첩 슬롯이라 값을 여기서 풀지 않고 그대로 자식 컴포넌트에 넘깁니다 — 각 자식(Divider / Collapsible
/ Gap)의 resolver 가 자기 기본값을 채웁니다. 그래서 이 슬롯들을 비워두면 자식의 기본값이 그대로 쓰이고, 일부 필드만 채우면 나머지는 자식 기본값이 남습니다.
동작 스펙 (Behavior)#
-
aside와sections가 모두 비면 내비게이션 밴드를 생략합니다.company·businessInfo·links·copyright가 모두 비면 법적 고지 블록도 생략하며 빈 블록 사이 간격을 남기지 않습니다. -
layout은 내비게이션 배치와 정렬을 선택합니다.horizontal은 감싸는 행,vertical과center는 세로 배치이며, 상단 구분선과 법적 고지 블록은 세로 흐름에 남습니다. -
businessInfo가 있을 때만 Collapsible 트리거를 만듭니다. 콜백이 없으면 초기businessInfoExpanded에서 내부 토글하고,onBusinessInfoExpandedChanged가 있으면 새 값을 알린 뒤 호출자가 상태를 다시 전달해야 합니다. -
showDivider가 켜져야 상단 구분선이 보이며, 법적 링크 사이 눈금은 두 항목 사이에만 삽입합니다. 링크 이동과 클릭 이벤트는 슬롯에 넣은 자식이 담당합니다.
사용 가이드라인 (Usage Guidelines)#
✅ Do#
콘텐츠 밀도에 맞는 layout 선택
Footer(
aside: const Text('© 2026 CoUI'),
sections: const [],
layout: CoreFooterLayout.center,
)
섹션 없이 카피라이트만 있는 얇은 푸터에는 center(세로 stack + 중앙 정렬)가, 여러 링크 섹션이 있는 푸터에는 기본값 horizontal(wrap 가능한 한 줄)이 맞습니다. 반대로 고르면 섹션 하나가 한쪽으로 치우치거나, 여러 섹션이 불필요하게 세로로 길게 늘어집니다.
❌ Don't#
semanticLabel에 빈 문자열 전달 금지
// ❌ 빈 문자열은 플랫폼마다 다르게 처리됨
Footer(semanticLabel: '', sections: const [])
// ✅ 라벨을 직접 정하지 않을 거라면 생략 — 로케일 폴백이 채움
Footer(sections: const [])
semanticLabel: ''을 넘기면 Flutter는 이름 없는 랜드마크를 역할째로 떨어뜨려 푸터가 랜드마크 목록에서 사라지고, Web은 role="contentinfo"를 유지한 채 이름만 빈 상태가 되어 두 플랫폼의 접근성 트리가 갈립니다.
접근성 (Accessibility)#
역할#
양 플랫폼 모두 contentinfo 랜드마크를 emit 하고, 이름도 아무것도 넘기지 않은 상태에서 붙습니다.
| 플랫폼 | 역할 | 이름 |
|---|---|---|
| Flutter |
SemanticsRole.contentInfo
(
CoUISemantics(role: .contentInfo, container: true)
)
|
semanticLabel
, 없으면 로케일 폴백(
footerLabel
—
Footer
/
바닥글
)
|
| Web | <footer role="contentinfo"> (중첩이면 tag: 'div') |
aria-label
=
semanticLabel
, 없으면
같은
로케일 폴백(
footerLabel
)
|
폴백은 바닥이지 덮개가 아닙니다 — semanticLabel 을 넘기면 그 이름이 이기고, Web 에서는 호출자가 attributes 로 직접 넣은
aria-label 도 폴백을 덮습니다.
키보드#
Footer 자체가 처리하는 키는 없습니다. 키보드 인터랙션은 호출자가 넣은 자식들이 각자 가져옵니다 — aside / CoreFooterNavData.children
/ links 의 링크·버튼, 그리고 businessInfo 를 넘겼을 때 합성되는 Collapsible 의 트리거(Enter / Space 로 토글)입니다.
포커스 관리#
Footer 는 포커스를 받지도 관리하지도 않습니다 — FocusNode / tabindex / 포커스 링이 없습니다. 포커스 가능한 요소는 호출자가 넣은 자식들과, 디스클로저를 쓸 때
Collapsible 이 스스로 만드는 트리거뿐입니다.
스크린 리더#
랜드마크 목록에는 양 플랫폼 모두 이름 붙은 contentinfo 로 나타납니다. 섹션 제목(CoreFooterNavData.title)은
일반 텍스트로 읽힙니다 — Flutter 는 Text, Web 은 <div> 라 heading 이 아닙니다.
사업자 정보 디스클로저의 펼침 상태는 합성된 Collapsible 이 알립니다 — Web 은 트리거에 aria-expanded, Flutter 는 그 컴포넌트의 시맨틱을 그대로 씁니다. 푸터는 여기에 아무것도 덧붙이지 않습니다.
알려진 제약#
-
섹션 제목에 heading 레벨이 없습니다(
h2~h6/SemanticsRole.header미emit). 스크린 리더 사용자가 heading 단위로 푸터 섹션을 건너뛸 수 없습니다. -
링크 그룹에 내비게이션·리스트 구조가 없습니다.
CoreFooterNavData라는 이름과 달리role="navigation"/<nav>도, list / listitem 구조도 emit 하지 않아 "링크 5개" 같은 개수 안내가 나오지 않습니다. 법적 고지 블록의links줄도 같습니다. - 행 안의 hairline 눈금은 장식입니다. 회사명↔디스클로저, 링크↔링크 사이의 세로 눈금은 시각 구분자일 뿐이라 스크린 리더가 항목 경계를 읽어주지 않습니다 — 항목 사이의 구분은 눈으로만 전달됩니다.
-
businessInfoLabel이 라벨을 다 말해야 합니다. 트리거는 이 슬롯의 텍스트와Collapsible이 그린 셰브론뿐이라, 라벨이 "자세히" 처럼 무엇을 여는지 말하지 않으면 스크린 리더에서 그 트리거는 맥락 없이 읽힙니다. -
semanticLabel: ''(빈 문자열)은 두 플랫폼이 다르게 처리합니다. Flutter 는 이름 없는 랜드마크가 아무 말도 못 하므로 역할 자체를 떨어뜨려(→ 전역 접근성 축 의 역할 전제조건) 푸터가 랜드마크 목록에서 사라지고, Web 은role="contentinfo"를 유지한 채 이름만 빈 랜드마크가 됩니다. 이름을 직접 정하지 않을 거라면 빈 문자열 대신 생략하세요 — 그때 폴백이 채웁니다.
크로스 플랫폼 차이점 (Platform Differences)#
| 항목 | Flutter | Web |
|---|---|---|
| 레이아웃 구현 | Wrap / Column |
flex (flex-wrap / flex-col) |
| 루트 요소 | OutlinedContainer + CoUISemantics(role: .contentInfo) |
진짜 <footer> (tag 로 교체 가능 — 중첩 시 tag: 'div') |
| 회사명 / 저작권 주변 텍스트 스타일 | DefaultTextStyle.merge |
슬롯을 감싼 <div> 의 typography class |
| 사업자 정보 디스클로저 | Collapsible (Flexible 안에서 남은 폭을 차지) |
Collapsible (flex-1 min-w-0) |
| 링크 줄 줄바꿈 | Wrap (linkRowSpacing 이 가로·세로 양쪽) |
flex + gap |
관련 컴포넌트 (Related Components)#
- NavigationBar: 상단 내비게이션
- Dock: 모바일 하단 탭 내비게이션
- Collapsible: 사업자 정보 디스클로저가 합성하는 컴포넌트 — 셰브론·펼침 애니메이션·상태를 소유
- Divider: 상단 구분선과 법적 고지 행 안의 hairline 눈금
- Link:
links줄에 넣는 항목 - Gap: 섹션 제목과 본문 사이
- Text: 제목과 본문이 상속하는 글자